pydantic_settings 使用方法
Pydantic Settings 完整使用指南
pydantic_settings 是 Pydantic V2 中用于管理应用程序配置的强大工具,支持从多种来源加载配置(环境变量、.env 文件、命令行参数等)。
✅ 安装
pip install pydantic-settings
🧩 基础用法
1. 最简单的配置类
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
port: int = 8000
settings = Settings()
print(settings.app_name) # MyApp
print(settings.debug) # False
print(settings.port) # 8000
2. 从环境变量加载
# 设置环境变量
# export APP_NAME="ProductionApp"
# export DEBUG="true"
# export PORT="9000"
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
port: int = 8000
settings = Settings()
print(settings.app_name) # ProductionApp(从环境变量读取)
print(settings.debug) # True
print(settings.port) # 9000
📁 从 .env 文件加载
创建 .env 文件
APP_NAME=MyProductionApp
DEBUG=true
PORT=8080
DATABASE_URL=postgresql://localhost/mydb
配置类
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str
debug: bool
port: int
database_url: str
class Config:
env_file = ".env" # 指定 .env 文件
env_file_encoding = "utf-8" # 指定编码
settings = Settings()
print(settings.app_name) # MyProductionApp
print(settings.debug) # True
print(settings.port) # 8080
print(settings.database_url) # postgresql://localhost/mydb
🔐 字段验证与必填
使用 Field 定义字段
from pydantic_settings import BaseSettings
from pydantic import Field, validator
class Settings(BaseSettings):
app_name: str = Field(default="MyApp", description="应用名称")
api_key: str = Field(..., description="API密钥(必填)") # ... 表示必填
max_connections: int = Field(default=100, ge=1, le=1000) # 1 <= max_connections <= 1000
debug: bool = Field(default=False)
class Config:
env_file = ".env"
# 如果没有设置 API_KEY 环境变量,会报 ValidationError
自定义字段名
from pydantic_settings import BaseSettings
from pydantic import Field
class Settings(BaseSettings):
database_url: str = Field(env="DB_URL") # 从 DB_URL 环境变量读取
secret_key: str = Field(env="SECRET_KEY")
# .env 文件
# DB_URL=postgresql://localhost/mydb
# SECRET_KEY=very-secret
🛠 配置模型设置
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
# 使用新的 SettingsConfigDict(推荐)
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False, # 环境变量不区分大小写
extra="forbid", # 禁止额外字段
)
🔐 敏感信息处理
from pydantic_settings import BaseSettings
from pydantic import SecretStr, SecretBytes
class Settings(BaseSettings):
api_key: SecretStr
password: SecretStr
settings = Settings(api_key="secret123", password="mypassword")
print(settings.api_key) # SecretStr('**********')
print(settings.api_key.get_secret_value()) # secret123
🧩 配置来源优先级
Pydantic Settings 按以下顺序加载配置(高 → 低):
- 构造函数参数(最高优先级)
- 环境变量
- .env 文件
- 字段默认值(最低优先级)
# 环境变量: APP_NAME="EnvApp", DEBUG="false"
class Settings(BaseSettings):
app_name: str = "DefaultApp"
debug: bool = True
class Config:
env_file = ".env"
# 构造函数传参覆盖所有其他来源
settings = Settings(app_name="CodeApp") # app_name="CodeApp", debug=False
🧪 嵌套配置
from pydantic_settings import BaseSettings
from pydantic import BaseModel
class DatabaseConfig(BaseModel):
host: str = "localhost"
port: int = 5432
name: str = "mydb"
class Settings(BaseSettings):
app_name: str = "MyApp"
database: DatabaseConfig = DatabaseConfig()
class Config:
env_prefix = "APP_" # 环境变量前缀
# 环境变量: APP_DATABASE_HOST="prod-db", APP_DATABASE_PORT="5433"
📋 配置验证器
from pydantic_settings import BaseSettings
from pydantic import field_validator
class Settings(BaseSettings):
host: str = "localhost"
port: int = 8000
@field_validator("port")
def validate_port(cls, v):
if v < 1 or v > 65535:
raise ValueError("端口必须在 1-65535 之间")
return v
@field_validator("host")
def validate_host(cls, v):
if not v:
raise ValueError("主机名不能为空")
return v
🚀 实际应用示例
from pydantic_settings import BaseSettings
from pydantic import Field, PostgresDsn, validator
from typing import Optional
class Settings(BaseSettings):
# 应用配置
app_name: str = "FastAPI App"
debug: bool = Field(default=False, env="DEBUG")
version: str = "1.0.0"
# 数据库配置
database_url: PostgresDsn = Field(
default="postgresql://localhost/defaultdb",
env="DATABASE_URL"
)
# Redis配置
redis_host: str = Field(default="localhost", env="REDIS_HOST")
redis_port: int = Field(default=6379, env="REDIS_PORT")
# API配置
api_key: str = Field(..., env="API_KEY") # 必填
allowed_hosts: list[str] = Field(
default=["localhost"],
env="ALLOWED_HOSTS"
)
class Config:
env_file = ".env"
env_file_encoding = "utf-8"
case_sensitive = False
# 使用
settings = Settings()
# 验证配置
print(f"App: {settings.app_name}")
print(f"Debug: {settings.debug}")
print(f"DB: {settings.database_url}")
print(f"Redis: {settings.redis_host}:{settings.redis_port}")
🧩 自定义配置源(高级)
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from typing import Dict, Any
class CustomConfigSource(PydanticBaseSettingsSource):
def __call__(self) -> Dict[str, Any]:
# 从自定义源加载配置
return {
"app_name": "CustomApp",
"custom_field": "custom_value"
}
class Settings(BaseSettings):
app_name: str = "DefaultApp"
custom_field: str = "default"
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
env_settings,
dotenv_settings,
CustomConfigSource(settings_cls), # 自定义源
file_secret_settings,
)
✅ 最佳实践
- 使用
.env文件管理开发环境配置 - 敏感信息使用
SecretStr类型 - 必填字段使用
Field(...) - 类型验证使用
Field(ge=1, le=100)等参数 - 配置类实例化一次,全局使用
- 使用
SettingsConfigDict替代旧的Config类
# config.py - 推荐的配置管理方式
from pydantic_settings import BaseSettings
from pydantic import Field
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = Field(default=False, env="DEBUG")
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
"case_sensitive": False,
}
settings = Settings()
# main.py
from config import settings
print(settings.app_name)
这样就完成了 Pydantic Settings 的完整使用指南!
settings_customise_sources 是 pydantic_settings.BaseSettings 中一个非常强大的方法,允许你自定义配置源的加载顺序和方式。通过重写这个方法,你可以添加自定义的配置源(如 YAML 文件、JSON 文件、数据库、远程配置中心等)。
✅ 基本语法
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic_settings.sources import (
PydanticBaseSettingsSource,
InitSettingsSource,
EnvSettingsSource,
DotEnvSettingsSource,
)
class CustomSource(PydanticBaseSettingsSource):
def get_field_value(self, field, field_name):
# 实现获取字段值的逻辑
pass
class MySettings(BaseSettings):
some_field: str = "default"
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: EnvSettingsSource,
dotenv_settings: DotEnvSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> tuple[PydanticBaseSettingsSource, ...]:
# 返回配置源的元组,顺序即为优先级(从高到低)
return (
init_settings, # 构造函数传入的参数(最高优先级)
env_settings, # 环境变量
dotenv_settings, # .env 文件
# 在这里添加自定义配置源
CustomSource(settings_cls),
file_secret_settings, # 文件密钥(最低优先级)
)
🧩 示例 1:从 YAML 文件加载配置
import yaml
from pathlib import Path
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from typing import Dict, Any
class YamlConfigSettingsSource(PydanticBaseSettingsSource):
def __init__(self, settings_cls: type[BaseSettings], yaml_file: str = "config.yaml"):
self.yaml_file = Path(yaml_file)
super().__init__(settings_cls)
def get_field_value(self, field: Any, field_name: str) -> tuple[Any, str, bool]:
"""
返回: (value, key, is_complex)
"""
if self.yaml_file.exists():
with open(self.yaml_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
field_value = data.get(field_name)
return field_value, field_name, False # is_complex=False
return None, field_name, False
def __call__(self) -> Dict[str, Any]:
d: Dict[str, Any] = {}
if self.yaml_file.exists():
with open(self.yaml_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
d = {k: v for k, v in data.items() if v is not None}
return d
class Settings(BaseSettings):
app_name: str = "DefaultApp"
debug: bool = False
database_url: str = "sqlite:///:memory:"
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
):
return (
init_settings, # 构造函数参数
env_settings, # 环境变量
dotenv_settings, # .env 文件
YamlConfigSettingsSource(settings_cls, yaml_file="config.yaml"), # 自定义 YAML 源
file_secret_settings, # 文件密钥
)
# 使用
settings = Settings()
print(settings.model_dump())
config.yaml
app_name: "MyAwesomeApp"
debug: true
database_url: "postgresql://localhost/mydb"
🧩 示例 2:从 JSON 文件加载配置
import json
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from typing import Dict, Any
class JsonConfigSettingsSource(PydanticBaseSettingsSource):
def __init__(self, settings_cls: type[BaseSettings], json_file: str = "config.json"):
self.json_file = json_file
super().__init__(settings_cls)
def get_field_value(self, field: Any, field_name: str) -> tuple[Any, str, bool]:
try:
with open(self.json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
field_value = data.get(field_name)
return field_value, field_name, False
except FileNotFoundError:
return None, field_name, False
def __call__(self) -> Dict[str, Any]:
try:
with open(self.json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
return {k: v for k, v in data.items() if v is not None}
except FileNotFoundError:
return {}
class Settings(BaseSettings):
app_name: str = "DefaultApp"
version: str = "1.0.0"
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
):
return (
init_settings,
env_settings,
JsonConfigSettingsSource(settings_cls, json_file="config.json"),
dotenv_settings,
file_secret_settings,
)
# config.json
# {
# "app_name": "MyApp",
# "version": "2.0.0"
# }
🧩 示例 3:从数据库加载配置(概念演示)
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from typing import Dict, Any
class DatabaseConfigSettingsSource(PydanticBaseSettingsSource):
def __init__(self, settings_cls: type[BaseSettings], db_connection=None):
self.db = db_connection or self._connect_to_db()
super().__init__(settings_cls)
def _connect_to_db(self):
# 模拟数据库连接
return {"app_name": "DBApp", "debug": False}
def get_field_value(self, field: Any, field_name: str) -> tuple[Any, str, bool]:
# 从数据库查询配置
value = self.db.get(field_name)
return value, field_name, False
def __call__(self) -> Dict[str, Any]:
# 返回所有配置
return self.db
class Settings(BaseSettings):
app_name: str = "DefaultApp"
debug: bool = False
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
):
return (
init_settings,
env_settings,
DatabaseConfigSettingsSource(settings_cls),
dotenv_settings,
file_secret_settings,
)
🧠 优先级顺序
在 settings_customise_sources 返回的元组中,越靠前的源优先级越高。例如:
return (
init_settings, # 优先级 1(最高)
env_settings, # 优先级 2
custom_yaml_source, # 优先级 3
dotenv_settings, # 优先级 4
file_secret_settings, # 优先级 5(最低)
)
如果 app_name 在环境变量和 YAML 文件中都有定义,会使用环境变量的值。
📌 总结
| 方法 | 用途 |
|---|---|
get_field_value |
获取单个字段值(可选实现) |
__call__ |
返回整个配置字典(必须实现) |
settings_customise_sources |
定义配置源的加载顺序和优先级 |
这个功能让你可以灵活地从任何数据源加载配置,非常适合微服务、云原生应用或需要动态配置的场景。

浙公网安备 33010602011771号