python 41 lines · 8 steps

Layered INI config loading in Python

A small toolkit that loads INI files, merges section defaults, and extracts typed database settings.

Explained by highlit
1from configparser import ConfigParser, ExtendedInterpolation
2from pathlib import Path
3 
4 
5def load_config(*paths, defaults=None):
6 parser = ConfigParser(
7 interpolation=ExtendedInterpolation(),
8 default_section="defaults",
9 )
10 if defaults:
11 parser.read_dict({"defaults": defaults})
12 
13 read = parser.read([Path(p) for p in paths], encoding="utf-8")
14 if not read:
15 raise FileNotFoundError(f"no config files found among {paths!r}")
16 
17 return parser
18 
19 
20def merged_section(parser, section, base="common"):
21 if not parser.has_section(section):
22 raise KeyError(f"missing section [{section}]")
23 
24 result = {}
25 if parser.has_section(base):
26 result.update(parser[base])
27 result.update(parser[section])
28 return result
29 
30 
31def database_settings(parser, env):
32 section = merged_section(parser, f"db.{env}", base="db.common")
33 return {
34 "host": section.get("host", "localhost"),
35 "port": section.getint("port", fallback=5432) if hasattr(section, "getint") else int(section.get("port", 5432)),
36 "name": section["name"],
37 "user": section["user"],
38 "password": section.get("password", ""),
39 "pool_size": int(section.get("pool_size", 5)),
40 "ssl": section.get("ssl", "false").lower() in ("1", "true", "yes"),
41 }
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1ExtendedInterpolation plus a default section lets INI files reference and inherit values without repetition.
  2. 2Merging a base section under a specific one gives you clean layered overrides from flat config files.
  3. 3Config values are always strings, so coerce and default them explicitly when you read them out.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Layered INI config loading in Python — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code