示例说明
环境变量进程序的第一站就该是校验站。BaseSettings 把每个类字段映射到同名环境变量(可加前缀隔离),类型注解即转换规则——bool 会正确解析真假,DSN 字段校验 URL 结构;多个 env_file 按序覆盖实现默认值与环境差异分层。lru_cache 保证单例,重复获取零开销。
技术要点
- env_prefix 隔离同名变量冲突
- Field 的 pattern 与范围约束前置校验
- lru_cache 提供进程级单例
代码解读
AppSettings 声明五个字段:环境名限定三种取值、调试开关默认关、数据库 DSN 必填、池大小限定区间、日志级别枚举校验。get_settings 捕获校验错误并把路径与原因拼成清单后退出进程——配置错误在启动时就带着完整说明失败。
使用建议
默认 env 文件进仓库,环境专属文件必须 ignore。敏感值不设默认,强制显式注入。测试里可用依赖注入覆盖设置而非改环境。
代码示例
from functools import lru_cache
from pydantic import Field, PostgresDsn, ValidationError
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppSettings(BaseSettings):
model_config = SettingsConfigDict(
env_file=('.env.defaults', '.env'),
env_file_encoding='utf-8',
env_prefix='APP_',
extra='ignore',
case_sensitive=False,
)
environment: str = Field(default='development', pattern='^(dev|staging|prod)$')
debug: bool = False
database_dsn: PostgresDsn
pool_size: int = Field(default=10, ge=1, le=100)
log_level: str = Field(default='info', pattern='^(debug|info|warning|error)$')
@lru_cache
def get_settings() -> AppSettings:
try:
return AppSettings()
except ValidationError as exc:
errors = '; '.join(
f"{'.'.join(str(p) for p in e['loc'])}: {e['msg']}"
for e in exc.errors()
)
raise SystemExit(f'invalid configuration -> {errors}') from exc
settings = get_settings()
print('running in', settings.environment, 'pool', settings.pool_size)