DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

pydantic-settings 2.16.1 显式 secrets_dir 为何仍读取旧目录

包装 file_secret_settings 时,2.16.1 会先采用被包装源的目录。把运行时目录统一交给 Settings(_secrets_dir=...),同时核对环境变量覆盖,避免悄悄读取旧密钥。

给 NestedSecretsSettingsSource 传了新目录,配置却仍从旧目录读取;两个目录都有同名文件时,程序甚至不会报错,只会得到旧值。pydantic-settings 2.16.1 中,包装现成的 file_secret_settings 与直接传入设置类,目录选择并不相同。

例如,模型的 secrets_dir 是目录 A,定制配置源时又写了:

NestedSecretsSettingsSource(file_secret_settings, secrets_dir="/run/secrets/B")

此时被包装的源已经从模型配置解析出 A。2.16.1 会先取它的 secrets_dir,再考虑外层显式提供的 B。因此,确认文件存在和权限正常以后,还要检查实际使用了哪一个目录。

让目录只从一个入口传入

需要在部署时选择目录的项目,可以继续包装 file_secret_settings,但不要在包装器里另传 secrets_dir。把目录交给 Settings(_secrets_dir=...),让已经解析好的路径沿原配置源传下去:

from pydantic import SecretStr
from pydantic_settings import (
    BaseSettings,
    NestedSecretsSettingsSource,
    SettingsConfigDict,
)


class Settings(BaseSettings):
    app_key: SecretStr
    model_config = SettingsConfigDict(secrets_dir="/run/secrets/A")

    @classmethod
    def settings_customise_sources(
        cls, settings_cls, init_settings, env_settings,
        dotenv_settings, file_secret_settings,
    ):
        return (
            init_settings,
            env_settings,
            dotenv_settings,
            NestedSecretsSettingsSource(file_secret_settings),
        )


settings = Settings(_secrets_dir="/run/secrets/B")

这段配置假定 B 是应用有权读取的目录,其中有名为 app_key 的文件。实际项目若使用嵌套子模型,还需保留原来的 secrets_nested_delimiter 或 secrets_nested_subdir 设置;更换目录不会替你改变文件命名规则。

上面的配置源顺序仍允许构造参数、环境变量和 dotenv 覆盖文件秘密。判断目录选择时,应在隔离环境使用不敏感的标记值,并排除这些更高优先级的输入,否则读取结果相同,也可能只是环境变量一直获胜。不要把真实密钥打印到日志里证明来自哪个目录。

如果目录永远固定,也可以只在模型配置中声明,包装器不再重复声明。应避免同时在模型、源构造函数和运行时传入三个互相冲突的路径。

直接传设置类会改变运行时覆盖能力

NestedSecretsSettingsSource(settings_cls, secrets_dir=B) 可以避开现成源已带着 A 的情况,但它没有继承 file_secret_settings 上已经解析好的运行时目录。项目若依赖 Settings(_secrets_dir=C) 切换租户或部署目录,不能只换构造方式就认为这种覆盖仍然有效。

2.16.1 的正式实现仍先取被包装源的路径。后续版本若改为外层显式目录优先,原来同时传 B 和 C 的配置也可能改变结果。升级时要分别核对“只有模型目录”“运行时覆盖”“包装器另传目录”三种调用,不能把不同入口当成等价写法。

修订后,用两个隔离目录中不同的非敏感标记检查读取结果;再检查目标目录不存在、必填文件缺失以及原环境变量覆盖的行为。缺失文件有可能由默认值或其他源补上,仅仅成功创建 Settings 不足以证明目录选对了。