python 52 lines · 6 steps

Loading typed config from environment variables

Typed helpers parse environment variables into an immutable, cached configuration object.

Explained by highlit
1import os
2from dataclasses import dataclass
3from functools import lru_cache
4 
5 
6def _get_bool(key: str, default: bool) -> bool:
7 value = os.environ.get(key)
8 if value is None:
9 return default
10 return value.strip().lower() in {"1", "true", "yes", "on"}
11 
12 
13def _get_int(key: str, default: int) -> int:
14 value = os.environ.get(key)
15 if value is None or not value.strip():
16 return default
17 try:
18 return int(value)
19 except ValueError as exc:
20 raise RuntimeError(f"{key} must be an integer, got {value!r}") from exc
21 
22 
23def _get_list(key: str, default: list[str]) -> list[str]:
24 value = os.environ.get(key)
25 if not value:
26 return default
27 return [item.strip() for item in value.split(",") if item.strip()]
28 
29 
30@dataclass(frozen=True)
31class Config:
32 database_url: str
33 port: int
34 debug: bool
35 max_connections: int
36 allowed_hosts: list[str]
37 
38 
39@lru_cache(maxsize=1)
40def load_config() -> Config:
41 try:
42 database_url = os.environ["DATABASE_URL"]
43 except KeyError as exc:
44 raise RuntimeError("DATABASE_URL is required") from exc
45 
46 return Config(
47 database_url=database_url,
48 port=_get_int("PORT", 8000),
49 debug=_get_bool("DEBUG", False),
50 max_connections=_get_int("MAX_CONNECTIONS", 10),
51 allowed_hosts=_get_list("ALLOWED_HOSTS", ["localhost"]),
52 )
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Centralizing env parsing into typed helpers keeps coercion logic consistent and testable.
  2. 2Failing loudly on missing or malformed required values catches misconfiguration at startup.
  3. 3A frozen dataclass plus lru_cache gives you an immutable config loaded exactly once.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Loading typed config from environment variables — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code