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
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1ExtendedInterpolation plus a default section lets INI files reference and inherit values without repetition.
- 2Merging a base section under a specific one gives you clean layered overrides from flat config files.
- 3Config values are always strings, so coerce and default them explicitly when you read them out.
Related explainers
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 steps
typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import * as Joi from 'joi';
Validating env config at boot in NestJS
configuration
schema-validation
environment-variables
Intermediate
8 steps
ruby
class UserAgentParser BROWSERS = [ [/Edg\/([\d.]+)/, "Edge"], [/OPR\/([\d.]+)/, "Opera"],
Parsing user-agent strings in Ruby
regex
pattern-matching
lookup-tables
Intermediate
8 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
javascript
function evaluate(expression) { const tokens = tokenize(expression); let pos = 0;
Building a recursive descent calculator
parsing
recursion
operator-precedence
Intermediate
8 steps
python
import random from typing import Iterator, List
How reservoir sampling picks k items
reservoir-sampling
streaming
randomness
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/layered-ini-config-loading-in-python-explained-python-f352/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.