Python Bindings
The Python binding has a book of its own:
→ dynamic-config for Python
pip install dynamic-config-py # the import is `dynamic_config`
pip install dynamic-config-py[pydantic] # + Pydantic models
pip install dynamic-config-py[msgspec] # + msgspec Structs
pip install dynamic-config-py[remote] # + the Rust etcd and Vault clients
from dataclasses import dataclass
from dynamic_config import DynamicConfig
@dataclass
class Database:
host: str = "localhost"
port: int = 5432
db = (
DynamicConfig(Database, key="db")
.file("config.toml")
.env("APP_")
.init_and_current() # a Database instance — cached, not re-validated
)
Rust resolves, your schema validates, Python reads a cache. This engine
does the sources, the layering, the profiles, the watcher, the
last-known-good recovery and the provenance; a dataclasses.dataclass, a
Pydantic model, a msgspec.Struct or Values does the validating, once per
successful resolve rather than once per read.
The Python documentation is its own book, on the same site. It links back here for precedence, document shape, schemaless configuration and telemetry — engine behaviour, identical in every language.
What is in it
| Chapter | What it answers |
|---|---|
| API Reference | Every method, every argument, every default |
| Callbacks | on_reload, on_change, scoped guards, the thread a hook runs on |
| Async & asyncio | init_async, async for config.changes(), which pool pays |
| Data Types | What a schema may be, and what each kind validates |
| Web Frameworks | FastAPI, Flask, Django |
| Telemetry | status(), and the Prometheus exposition |
| Remote Stores | A store written in Python, and the second wheel that carries the Rust ones |
| Implementation Details | What crosses the boundary, and how often |
| Free-Threaded CPython | The cp314t wheel, and what was measured |
| Limitations | What it will not do, and why |