Pydantic Settings 是基于 Pydantic 的数据验证和序列化机制,为应用提供了一种集中式、类型安全的配置管理解决方案。 它不仅可以通过环境变量、.env 文件加载配置,还能通过自定义配置源,从 YAML、JSON 文件甚至远程配置中心获取数据, 并对加载的数据进行类型校验和转换。得益于此,开发者在配置管理上可以实现更灵活的加载顺序、覆盖策略以及环境间隔离。
使用 Pydantic Settings 时,配置数据的加载来源主要按照以下优先级进行:
这一机制可以通过覆写 settings_customise_sources 方法进行自定义,
从而使得开发者能够根据项目不同的需求,构造特定来源的加载顺序并处理对应的数据转换逻辑。
在默认情况下,继承了 BaseSettings 的配置类会自动尝试从环境变量中读取字段的值,若未找到则使用默认值。
同时,使用 env_prefix 变量可以为各个字段设置前缀,使得多环境部署更为规范。
如果结合了 python-dotenv 包,配置文件 .env 可以自动加载,从而使得本地开发和生产环境配置分离。
为了保护敏感信息,例如数据库密码或者 API 密钥,
Pydantic Settings 允许通过配置 _secrets_dir 参数来从专门的秘密目录中加载数据,
这些秘密数据将会覆盖其他来源中同名的配置项,但环境变量和 .env 文件中的配置优先级更高。
Pydantic Settings 还可以集成命令行参数解析,允许开发者在运行时通过 CLI 重写配置项。 通过启用CLI解析,可以自动为字段添加命令行参数,支持位置参数和子命令,这对于需要通过命令行启动脚本时调整配置的场景非常有用。
借助自定义配置源,开发者可以定义一个函数或独立类用以从 YAML、JSON、远程服务等非常规来源加载数据, 并将加载的数据以字典形式返回给 Pydantic。可以自定义如何处理加载到的数据、预处理数据格式、转换默认值等, 从而实现所有配置数据的一次整合。加载顺序的设计十分关键,因为后加载的数据会覆盖先加载的数据。
利用 env_prefix 和自定义加载源,可以为不同环境(如生产、测试、开发)配置不同来源的加载策略。
比如在开发环境中优先加载 .env 文件,而在生产环境中则可设定专门的秘密目录或者远程配置中心。
同时,通过为环境变量添加前缀,避免了不同环境中的配置项冲突问题,确保了数据隔离与安全。
以下部分详细介绍一些应用场景下的高级用法。
除了内置加载器,开发者可以编写自定义加载函数以从特定格式文件载入数据。例如,我们可以编写一个读取 YAML 文件的加载函数,
再通过在 Settings 类的 model_config 中定义 customise_sources 参数来将其整合到加载过程中。
# 示例:定义从 YAML 文件加载配置的自定义源
import os
import yaml
from pydantic_settings import BaseSettings, SettingsConfigDict
def yaml_config_settings_source(settings: BaseSettings) -> dict:
# 使用环境变量指定YAML文件路径,默认为 'config.yaml'
file_path = os.getenv("YAML_CONFIG_PATH", "config.yaml")
try:
with open(file_path, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
return data if isinstance(data, dict) else {}
except FileNotFoundError:
# 文件未找到时返回空字典
return {}
except Exception as e:
print(f"加载 YAML 配置失败: {e}")
return {}
class AppSettings(BaseSettings):
app_name: str = "My Application"
debug: bool = False
port: int = 8000
model_config = SettingsConfigDict(
env_prefix="MYAPP_",
# 自定义来源顺序:初始默认值 -> YAML文件 -> 环境变量
customise_sources=(
lambda settings: settings.model_dump(),
yaml_config_settings_source,
)
)
if __name__ == "__main__":
settings = AppSettings()
print("应用名称:", settings.app_name)
print("调试模式:", settings.debug)
print("端口:", settings.port)
在该示例中,我们首先使用初始化的默认值,随后加载 YAML 文件中的配置,并最后允许环境变量来覆盖前面的值。通过这种 加载顺序,即使 YAML 文件中的配置存在,也可以通过设置环境变量来覆盖相应的配置项,实现灵活的配置管理设计。
除了 YAML 文件,自定义配置还可支持 JSON、TOML 甚至 Pyproject.toml 文件。开发者只需根据相应数据格式编写加载函数, 并整合到设置的加载顺序中。例如,通过读取 JSON 文件获得配置信息:
import json
from pydantic_settings import BaseSettings, SettingsConfigDict
def json_config_settings_source(settings: BaseSettings) -> dict:
file_path = os.getenv("JSON_CONFIG_PATH", "config.json")
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data if isinstance(data, dict) else {}
except Exception:
return {}
class JsonAppSettings(BaseSettings):
service_url: str = "http://localhost"
timeout: int = 30
model_config = SettingsConfigDict(
env_prefix="MYAPP_",
customise_sources=(
lambda settings: settings.model_dump(),
json_config_settings_source,
)
)
此外,也有许多现成的加载源支持方法,如从 TOML 文件加载、从 pyproject.toml 文件中读取以及从 Docker Secrets 加载敏感数据, 这些方式可以大大减少项目中配置管理的复杂性。
在配置管理中,配置数据往往不是单层的。通过使用 Pydantic 的嵌套模型,可以定义更复杂的数据结构并进行校验。
默认情况下,Pydantic Settings 对嵌套模型采用完整覆盖策略,但如果需要支持对嵌套对象的部分更新,
则可以通过设置 nested_model_default_partial_update 为 True 允许加载部分数据后更新模型。
例如,一个表示数据库连接的嵌套模型可能含有 host、port、username 与 password 四个属性, 如果只希望通过环境变量更改 host 和 port,而 username 与 password 保持默认不变, 允许部分更新的配置源便能很好的支持这种需求。
在处理 API 密钥、数据库密码等敏感信息时,Pydantic 提供了 SecretStr 用于安全存储。通过这种类型,
输出配置数据时不会直接显示敏感内容,而是仅返回掩码信息。同时,配合秘密文件目录的配置,可以确保敏感信息只在
指定位置被加载,并且可以通过环境变量或 .env 文件来实现覆盖更新。
借助 CLI 集成功能,Pydantic Settings 能够把命令行提供的参数直接映射为配置项,解决了在脚本执行时需要快速调整配置的问题。
通过启用 cli_parse_args=True,配置类不仅能自动识别命令行输入,还支持子命令、位置参数、布尔值标记等深度解析功能,
并且允许对 CLI 参数的别名进行配置,确保用户在使用时获得良好的体验。
| 加载源类别 | 优先级 | 常见用途 |
|---|---|---|
| 初始化参数 | 最高 | 在代码中直接传入特定配置项 |
| CLI 参数 | 高 | 命令行启动时临时覆盖配置 |
| 环境变量 | 中 | 通过系统环境维护配置,例如使用 env_prefix 管控 |
| .env 文件 | 低 | 本地开发常用,自动加载配置 |
| 秘密目录 | 较低 | 安全加载敏感信息,如 API 密钥 |
| 默认值 | 最低 | 预设固定默认配置 |
为了全面展示如何利用各种高级特性构建一个健壮的配置管理方案,以下给出一个较为完整的示例, 该示例结合了环境变量、.env 文件自定义 YAML/JSON 加载以及 CLI 参数解析,演示如何设计加载优先级。
import os
import json
import yaml
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic.types import SecretStr
# 自定义 YAML 配置加载函数
def yaml_config_source(settings: BaseSettings) -> dict:
path = os.getenv("YAML_CONFIG_PATH", "config.yaml")
try:
with open(path, "r", encoding="utf-8") as file:
config = yaml.safe_load(file)
return config if isinstance(config, dict) else {}
except Exception:
return {}
# 自定义 JSON 配置加载函数
def json_config_source(settings: BaseSettings) -> dict:
path = os.getenv("JSON_CONFIG_PATH", "config.json")
try:
with open(path, "r", encoding="utf-8") as file:
config = json.load(file)
return config if isinstance(config, dict) else {}
except Exception:
return {}
class DatabaseSettings(BaseSettings):
host: str = "localhost"
port: int = 5432
username: str = "user"
password: SecretStr = SecretStr("default_password")
class AppConfig(BaseSettings):
app_name: str = "My Application"
debug: bool = False
timeout: int = 30
database: DatabaseSettings = DatabaseSettings()
model_config = SettingsConfigDict(
env_prefix="MYAPP_",
# 加载顺序:初始默认 -> YAML 配置 -> JSON 配置 -> 环境变量 -> CLI 参数覆盖(若启用)
customise_sources=(
lambda s: s.model_dump(), # 初始默认值
yaml_config_source, # 从 YAML 文件加载
json_config_source, # 从 JSON 文件加载
# CLI 与环境变量加载由 Pydantic 内置逻辑管理
)
)
if __name__ == "__main__":
# 模拟 CLI 参数与环境变量设置
os.environ["MYAPP_APP_NAME"] = "Updated Application"
os.environ["MYAPP_DEBUG"] = "True"
os.environ["MYAPP_DATABASE__HOST"] = "db.example.com"
config = AppConfig()
print("应用名称:", config.app_name)
print("调试模式:", config.debug)
print("数据库主机:", config.database.host)
print("数据库端口:", config.database.port)
在上述示例中,程序首先使用类中定义的默认值,然后尝试从 YAML 和 JSON 中加载额外配置, 最后通过环境变量进行覆盖。这种方式不仅让配置管理逻辑清晰,还具备较高的灵活性, 使得不同环境之间可以轻松切换和复用相同的配置方案。
在实际项目中,配置管理往往伴随着多个需求和挑战,包括不同环境变量的优先级、敏感信息的保护、 CLI 参数的适配以及同一应用内多层嵌套配置管理。以下为一些最佳实践的建议:
开发者在定义自定义加载源时需仔细规划各来源的优先级,通常希望环境变量与 CLI 参数具备最高优先级, 这样便于在部署以及运行时对配置进行即时调整。对加载顺序的灵活控制能确保各层覆盖策略符合业务需求。
对于敏感配置,如密码、密钥等数据,应借助 SecretStr 类型以及秘密文件目录来保护数据安全。 同时,尽可能将敏感项隔离于其他配置数据外部,确保其不会因错误加载而泄露。
在开发、测试和生产环境下通常有不同的配置要求。利用 env_prefix 可以动态调整环境变量名称, 自定义加载源则可根据不同的文件路径加载相应环境下的配置,实现配置管理的统一和环境间的隔离。
继承 Pydantic 的强大优势,所有配置项都应配合类型注解、数据校验以及必要的默认值, 即使在大规模配置加载中也能保证数据格式正确,减少运行时错误风险,从开发阶段即确保数据质量。
Pydantic Settings 作为一个配置管理库,通过内置和自定义配置源的组合大大提升了数据验证和加载灵活性。 它不仅支持使用环境变量、.env 文件、秘密文件加载基本配置, 还允许开发者针对 YAML、JSON 等非标准文件格式自定义加载逻辑。与此同时,通过支持 CLI 参数解析与多环境管理, 用户能够在不同部署场景下高效重写、覆盖和更新配置,确保数据安全和应用稳定。实践中遵循优先级设计、 数据类型安全及敏感数据保护等最佳实践,可以构建出一整套灵活、可靠的配置管理方案, 有效应对复杂的开发和部署需求。