在对列表使用Dynaconf的 @get时,会产生一个意外的嵌套字典结构

编程语言 2026-07-12

我有一些配置值需要在配置树的多个位置可见。我正在使用Dynaconf 3.2.12,在Python 3.8、3.11和 3.14.2上进行测试。我不确定这是一个bug还是我理解上的某些限制。以下是一个最小示例,用来演示这个问题。

# dynaconf_example.py
from dynaconf import Dynaconf

settings = Dynaconf(
    settings_files=['dynaconf_example.toml'],
    environments=True,
    env_switcher='EXAMPLE_ENV',
)
# dynaconf_example.toml
[default]
# this doesn't seem to matter
# dynaconf_merge = true

[nonprod]
# this doesn't seem to matter
# dynaconf_merge = true

[prod]
# this doesn't seem to matter
# dynaconf_merge = true

[default.google]
domain = 'example.org'

[nonprod.google]
domain = 'nonprod.example.org'

[prod.google]
domain = 'prod.example.org'

# this doesn't seem to matter
#[default.google.calendar]
#dynaconf_merge = true
#calendar_ids = []

[nonprod.google.calendar]
calendar_ids = ['a', 'b']

[prod.google.calendar]
calendar_ids = ['c', 'd']

[default.carrot]
google = '@get google'

[default.celery.google]
domain = '@get google.domain'

[default.celery.google.calendar]
calendar_ids = '@get google.calendar.calendar_ids'

[default.onion.google]
domain = '@get google.domain'
calendar.calendar_ids = '@get google.calendar.calendar_ids'

使用 dynaconf get 命令可以显示我想要的结果,适用于 carrot 分支:

$ EXAMPLE_ENV=nonprod dynaconf -i dynaconf_example.settings get carrot|jq -C .
{
  "google": {
    "calendar": {
      "calendar_ids": [
        "a",
        "b"
      ]
    },
    "domain": "nonprod.example.org"
  }
}

而我实际得到的结果,是在 celeryonion 分支上的:

$ EXAMPLE_ENV=nonprod dynaconf -i dynaconf_example.settings get celery|jq -C .
{
  "google": {
    "calendar": {
      "calendar_ids": {
        "calendar_ids": [
          "a",
          "b"
        ]
      }
    },
    "domain": "nonprod.example.org"
  }
}
$ EXAMPLE_ENV=nonprod dynaconf -i dynaconf_example.settings get onion|jq -C .
{
  "google": {
    "calendar": {
      "calendar_ids": {
        "calendar_ids": [
          "a",
          "b"
        ]
      }
    },
    "domain": "nonprod.example.org"
  }
}

这显然是一个简化示例,包含了一些伪造的名称,因此虽然 carrot 分支可以工作,但在 google 级别还有很多我不想复制的其他内容。我尝试在不同位置设置 dynaconf_merge,并在 default 环境中为 calendar_ids 设置一个空列表,但都无济于事。

(可能相关:我在从 .py 文件加载值时引入的中间字典/映射/容器也有类似问题,这个文件实现使用 importlib_resources;我能够解决这些问题,因为得到的值是字符串,所以可以使用 @format {this.x.y.z} 获取所需的值。对于列表来说,这行不通;最终我得到的是一个字符串中的列表。)

解决方案

这确实是一个bug,现已在3.2.12版本中修复:https://github.com/dynaconf/dynaconf/issues/1367

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章