返回首页

使用 Pydantic 在 Python 中加载 TOML 配置

模块通过 tomllib 加载 settings.toml,使用 lru_cache 缓存并验证 Pydantic 模型。支持任何配置类的 TypeVar 类型提示。适用于生产应用,将逻辑与参数分离。

在 Python 中解析 settings.toml 和 Pydantic 验证
Advertisement 728x90

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:

Google AdInline article slot
[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 属性简化验证。

Google AdInline article slot
  • 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 机制在超限时淘汰旧项,但配置只需一个槽位。

Google AdInline article slot

优点:

  • 减少 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

Advertisement 728x90

继续阅读