我正在为 Python 3 应用程序构建一些配置逻辑,并尝试使用
pydantic
和 pydantic-settings
来管理验证等。我可以从 YAML 文件加载原始设置并从中创建我的设置对象。我还可以从环境变量中读取值。但我不知道如何使环境变量值优先于原始设置:
import os
import yaml as pyyaml
from pydantic_settings import BaseSettings, SettingsConfigDict
class FooSettings(BaseSettings):
foo: int
bar: str
model_config = SettingsConfigDict(env_prefix='FOOCFG__')
raw_yaml = """
foo: 13
bar: baz
"""
os.environ.setdefault("FOOCFG__FOO", "42")
raw_settings = pyyaml.safe_load(raw_yaml)
settings = FooSettings(**raw_settings)
assert settings.foo == 42
如果我在输入 yaml 中注释掉
foo: 13
,断言就会通过。如何使 env 值优先?
您确定要环境优先吗?虽然不是普遍存在,但环境变量具有最低优先级是很常见的(通常,顺序是内置默认值,然后是环境变量,然后是配置文件,然后是命令行选项)。偏离这个约定可能会令人惊讶。
您可以通过添加一个字段验证器来获得特定字段所需的行为,该验证器检查适当的环境变量,并优先使用该值而不是现有值(如果可用)。比如:
import os
import yaml as pyyaml
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import field_validator
class FooSettings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="FOOCFG__")
foo: int
bar: str
@field_validator("foo", mode="after")
@classmethod
def validate_foo(cls, val):
'''Always use the value from the environment if it's available.'''
if env_val := os.environ.get(f"{cls.model_config['env_prefix']}FOO"):
return int(env_val)
return val
raw_yaml = """
foo: 13
bar: baz
"""
os.environ.setdefault("FOOCFG__FOO", "42")
raw_settings = pyyaml.safe_load(raw_yaml)
settings = FooSettings(**raw_settings)
assert settings.foo == 42
如果您想对所有字段执行此操作,您可以使用模型验证器。