Python 应用中使用 Pydantic 读取和验证 settings.toml 配置
这个模块负责读取 settings.toml 文件,使用 tomllib 解析,借助 lru_cache 缓存结果,并用 Pydantic 验证各配置节。它将配置逻辑与应用参数分离,减少重复磁盘读取,并确保类型安全。
from functools import lru_cache
from pathlib import Path
from tomllib import load
from typing import Any, Type, TypeVar
from pydantic import BaseModel, SecretStr
ConfigType = TypeVar("ConfigType", bound=BaseModel)
class BotConfig(BaseModel):
token: SecretStr
@lru_cache
def parse_config_file() -> dict[str, Any]:
config_path = Path(__file__).resolve().parent.parent.joinpath("settings.toml")
if not config_path.exists():
error = "Could not find settings file"
raise ValueError(error)
with open(config_path, "rb") as file:
config_data = load(file)
return config_data
def get_config(model: Type[ConfigType], root_key: str) -> ConfigType:
config_dict = parse_config_file()
if root_key not in config_dict:
error = f"Key {root_key} not found"
raise ValueError(error)
return model.model_validate(config_dict[root_key])
为什么选择 TOML 和 Pydantic 处理配置
TOML 文件易读,解析后直接转为 Python 字典。像 [bot] 这样的节会变成嵌套字典。Pydantic 负责验证结构、类型转换,并用 SecretStr 隐藏敏感信息。
示例 TOML:
[bot]
token = "123456:ABCDEF"
解析后得到 {"bot": {"token": "123456:ABCDEF"}},验证则生成 BotConfig 对象。
使用 @lru_cache 缓存可跳过重复读取:首次调用解析,后续直接命中缓存。需重新加载时调用 parse_config_file.cache_clear()。
使用 pathlib 处理路径
Path(__file__).resolve().parent.parent.joinpath("settings.toml") 构建项目上级目录中文件的绝对路径。exists() 检查文件存在,parent 属性简化验证。
Path.joinpath():跨平台追加路径段。resolve():解析符号链接为绝对路径。- 以
"rb"模式打开:tomllib.load()要求二进制读取。
TypeVar 和 Pydantic 的类型提示
ConfigType = TypeVar("ConfigType", bound=BaseModel) 让 get_config 支持任意 Pydantic 模型,返回传入类型的实例。
Type[ConfigType]:期望模型类而非实例。model_validate():将字典转为验证后的对象,失败时抛ValidationError。- 字典用
Any:TOML 类型混合(str、int、bool、dict)。
扩展其他节:
class DatabaseConfig(BaseModel):
host: str
port: int
user: str
config = get_config(DatabaseConfig, "database")
缓存与装饰器
@lru_cache 根据参数存储结果(此处无参数,简单直接)。LRU 机制在超限时淘汰旧项,但配置只需一个槽位。
优点:
- 减少 I/O:磁盘只读一次。
- 幂等性:多次
get_config共享一次解析。 - 线程安全:标准库装饰器内置支持。
缺点:TOML 文件磁盘变更需 cache_clear() 才生效。
模块结构
- 模型(如
BotConfig):独立于加载器。 parse_config_file():解析完整 TOML。get_config():提取并验证单节。
这种关注点分离提升可测试性:可模拟路径或 TOML 字符串。
核心提示:
- 使用
tomllib(Python 3.11+),旧版回退tomli。 - 使用前始终用 Pydantic 验证配置。
- 缓存解析,但添加重载支持。
- 敏感信息用
SecretStr存储,避免日志/调试泄露。 - 用
pathlib构建路径,确保跨平台兼容。
— Editorial Team
暂无评论。