跳转到内容

Pydantic 设置

Pydantic 是 Python 生态中最强大、被应用最广(如 FastAPI)的数据校验库。 其子模块 pydantic-settings 允许开发者以 强类型模型(Model)的方式处理应用程序的全局配置。它自动解析外部输入,执行严格的类型强制转换(如将字符串 '8080' 自动转为整数 8080),极大提升了工程稳健性。


2. 核心机制:配置加载的优先级控制

Section titled “2. 核心机制:配置加载的优先级控制”

Pydantic 会从多个来源智能探测配置,优先级(从高到低)如下:

数据来源配置示例覆盖权限
1. 构造函数入参Settings(database_url='mem_db')最高优先级。硬编码,覆盖一切。
2. 系统环境变量终端执行 export DATABASE_URL=prod_db第二优先级。常用于 Docker 或 K8s 动态注入。
3. .env 配置文件文件内写入 DATABASE_URL=dev_db第三优先级。适合本地研发环境的统一配置。
4. 字段默认值模型内声明 database_url: str = "sqlite"兜底值。若上述来源皆无此项,则采用此值。

在 V2 版本中,配置管理依赖 pydantic_settings 库,并使用 SettingsConfigDict 进行驱动。

from functools import lru_cache
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppSettings(BaseSettings):
# Field alias 允许环境变量与代码变量名解耦
secret_key: str = Field(validation_alias="API_SECRET_KEY")
items_per_user: int = 10 # 默认值
# Pydantic v2 专属配置项
model_config = SettingsConfigDict(
env_file='.env', # 读取根目录下的 dotenv 文件
env_file_encoding='utf-8',
env_prefix='MYAPP_' # 安全前缀,仅读取以 MYAPP_ 开头的环境变量
)
# 使用 lru_cache 确保配置对象只被解析构建一次(单例模式)
@lru_cache
def get_settings() -> AppSettings:
return AppSettings()

3.2. 高阶用法:生命周期钩子 (model_post_init)

Section titled “3.2. 高阶用法:生命周期钩子 (model_post_init)”

有些配置参数无法直接从外部读取,需要依据其他已加载的基础参数在 初始化完成后动态计算得出

from typing import Optional
from pydantic import Field
from pydantic_settings import BaseSettings
class ServerConfig(BaseSettings):
host: str = Field(alias="HOST")
port: int = Field(alias="PORT")
# 声明衍生变量,初始暂为 None
base_url: Optional[str] = None
# 模型后置初始化方法 (Pydantic v2 专属)
def model_post_init(self, __context: any) -> None:
"""所有字段加载与强制类型转换完毕后立即触发"""
if self.host and self.port:
port_suffix = f":{self.port}" if self.port not in [80, 443] else ""
self.base_url = f"http://{self.host}{port_suffix}/api/v1"
else:
raise ValueError("HOST 或 PORT 配置缺失,无法初始化 BASE_URL")
# 假设环境中含有 HOST = "api.test.com", PORT = 8080
config = ServerConfig()
print(config.base_url) # 自动渲染为:http://api.test.com: 8080/api/v1

在 Pydantic v1 中,__root__ 允许将一个模型定义为 非字典结构 的原始数据类型(例如一个纯列表或单一字符串)。 在 Pydantic v2 中,该概念已被废弃,取而代之的是使用 RootModel 显式包装顶级非对象元素。