Čtení a validace settings.toml s Pydantic v Python aplikacích
Modul pro čtení settings.toml určuje cestu k souboru, parsuje ho pomocí tomllib, cachuje výsledek přes lru_cache a validuje sekce s Pydantic. To zajišťuje oddělení logiky od parametrů, minimalizuje opakované čtení z disku a garantuje type-safe kód.
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])
Proč TOML a Pydantic pro konfiguraci
TOML soubory jsou čitelné pro člověka a striktně se parsují do Python slovníků. Sekce jako [bot] se převádějí na vnořené dict. Pydantic kontroluje strukturu, převádí typy a maskuje tajemství přes SecretStr.
Příklad TOML:
[bot]
token = "123456:ABCDEF"
Parsování vrátí {"bot": {"token": "123456:ABCDEF"}}. Validace vytvoří objekt BotConfig.
Cachování s @lru_cache zabraňuje opakovanému čtení: první volání parsuje, další vrací cache. Pro reload použijte parse_config_file.cache_clear().
Práce s cestami přes pathlib
Path(__file__).resolve().parent.parent.joinpath("settings.toml") sestavuje absolutní cestu k souboru v nadřazeném adresáři projektu. Metody exists() a vlastnost parent usnadňují kontroly.
Path.joinpath(): připojuje segmenty cesty napříč platformami.resolve(): řeší symlinky na absolutní cestu.- Otevírání v
"rb": požadavektomllib.load()pro binární čtení.
Typizace s TypeVar a Pydantic
ConfigType = TypeVar("ConfigType", bound=BaseModel) umožňuje get_config pracovat s jakýmikoli Pydantic modely a vracet instanci předaného typu.
Type[ConfigType]: parametr je třída modelu, ne instance.model_validate(): validuje dict do objektu, hážeValidationErrorpři chybách.Anypro slovník: TOML obsahuje smíšené typy (str, int, bool, dict).
Rozšiřte pro další sekce:
class DatabaseConfig(BaseModel):
host: str
port: int
user: str
config = get_config(DatabaseConfig, "database")
Cachování a dekorátory
@lru_cache ukládá výsledek podle argumentů (zde bezargumentní funkce). LRU vyhazuje staré záznamy při limitu, ale pro config stačí jeden slot.
Výhody:
- Snížení I/O: disk se čte jednou.
- Idempotence: vícenásobné volání
get_configpoužívají jeden pars. - Thread-safe: standardní dekorátor je bezpečný.
Nevýhody: změny TOML na disku se ignorují do cache_clear().
Struktura modulu
- Modely (
BotConfig): nezávislé na loaderech. parse_config_file(): parsuje celý TOML.get_config(): extrahuje/validuje sekci.
Oddělení povinností zlepšuje testovatelnost: mockujte cesty nebo TOML řetězce.
Důležité body:
- Používejte
tomllib(Python 3.11+), fallback natomlipro starší verze. - Vždy validujte config s Pydantic před použitím.
- Cacheujte parsování, ale připravte reload.
- Ukládejte tajemství v
SecretStrpro maskování v logách/debugu. - Sestavujte cesty s
pathlibpro cross-platform kompatibilitu.
— Editorial Team
Zatím žádné komentáře.