Zpět na domů

Načítání TOML konfigurace s Pydantic v Pythonu

Modul načítá settings.toml přes tomllib, cachuje s lru_cache a validuje Pydantic modely. Podporuje typizaci TypeVar pro libovolné config třídy. Ideální pro production-aplikace s oddělením logiky a parametrů.

Parsování settings.toml a Pydantic-validace v Pythonu
Advertisement 728x90

Č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:

Google AdInline article slot
[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.

Google AdInline article slot
  • Path.joinpath(): připojuje segmenty cesty napříč platformami.
  • resolve(): řeší symlinky na absolutní cestu.
  • Otevírání v "rb": požadavek tomllib.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áže ValidationError při chybách.
  • Any pro 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.

Google AdInline article slot

Výhody:

  • Snížení I/O: disk se čte jednou.
  • Idempotence: vícenásobné volání get_config použí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 na tomli pro starší verze.
  • Vždy validujte config s Pydantic před použitím.
  • Cacheujte parsování, ale připravte reload.
  • Ukládejte tajemství v SecretStr pro maskování v logách/debugu.
  • Sestavujte cesty s pathlib pro cross-platform kompatibilitu.

— Editorial Team

Advertisement 728x90

Číst dál