Config Files with configparser
configparser is Python's standard-library tool for reading and writing INI files — plain-text configuration made of [sections] and key = value pairs — so you can keep settings out of your code and edit them by hand.
Learn Config Files with configparser in our free Python course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Hard-coding hosts, ports, and feature flags into your program means editing source every time something changes. A config file lets non-programmers tweak settings safely, and configparser makes reading them a one-liner.
An INI file groups settings into [sections] , each holding key = value lines. Create a ConfigParser , feed it the text (here with read_string ; from a real file you'd use config.read("app.ini") ), then access values like a nested dictionary:
Access is dictionary-style: config["section"]["key"] . Every value comes back as a string — converting to other types is the next step.
Because INI values are text, config["features"]["dark_mode"] is the string "true" , not a boolean. The typed getters convert for you — and getboolean cleverly understands many spellings of true and false:
Notice getint("server", "port") returns the integer 8080 , while the raw config["server"]["port"] is the string "8080" . Always use the typed getter when you need a real number or boolean.
Real config files don't always have every key. The fallback argument supplies a value when a key is missing, and the special [DEFAULT] section provides shared defaults that every section inherits:
configparser also writes INI. Assign a dictionary to each section, then call config.write(file) . To a real file you'd open it in text mode; here we write into an in-memory StringIO so it runs anywhere and we can print the result:
INI is great for simple, hand-edited settings — but it isn't the only option. Each format has a sweet spot:
Complete the code to read typed values from the config. Replace each ___ , then run it.
❌ Comparing a string value as if it were a bool
✅ Use the typed getter so "false" becomes the boolean False :
✅ Provide a fallback: config.getint("server", "port", fallback=8080) .
✅ Store values as strings: — and convert back with getint on read.
Build a config in code, write it to a StringIO buffer, then read that text back into a fresh parser and pull out typed values — proving a full write-then-read cycle.
Lesson complete — your settings live outside your code now!
You can read INI files with read_string and read , pull typed values with getint / getfloat / getboolean , lean on [DEFAULT] and fallback , write configs back out, and choose the right format for the job. Clean configuration is a hallmark of professional code.
🚀 Up next: Checkpoint — OOP & Standard Library — put it all together.
Practice quiz
What is the INI format built from?
- Nested JSON objects
- Indented YAML blocks
INI files group settings into [sections], each holding plain key = value lines.
What type does config['database']['port'] return when port = 5432?
- the string '5432'
- int
- float
- bool
Answer: the string '5432'. configparser reads every raw value as a string, so dictionary access gives '5432', not the integer 5432.
Which method converts a value to an integer?
- config.int(...)
- config.toInt(...)
- config.asint(...)
- config.getint(section, key)
Answer: config.getint(section, key). getint(section, key) parses the string value into a real int; getfloat and getboolean do the same for their types.
Which spellings does getboolean understand as truthy?
- Only 'true'
- true/false, yes/no, on/off, and 1/0
- Only 1 and 0
- Only 'True' with a capital T
Answer: true/false, yes/no, on/off, and 1/0. getboolean accepts true/false, yes/no, on/off, and 1/0 in a case-insensitive way.
What is the special [DEFAULT] section used for?
- Providing fallback values every other section inherits
- Storing only comments
- Marking the active section
- Holding secrets
Answer: Providing fallback values every other section inherits. Keys in [DEFAULT] are inherited by every section unless that section overrides them.
How do you supply a value for a key that may be missing from a section?
- Wrap it in try/except only
- Use config.default()
- Pass fallback=... to a getter, e.g. getint('api', 'port', fallback=443)
- It is impossible
Answer: Pass fallback=... to a getter, e.g. getint('api', 'port', fallback=443). The fallback argument returns a default when the key is absent instead of raising an error.
Which method parses an INI string directly (instead of a file)?
- config.parse(text)
- config.read_string(text)
- config.loads(text)
- config.read(text)
Answer: config.read_string(text). read_string parses INI text in memory; read() is for files on disk.
When writing a config, what type must the values you assign be?
- Any type
- Only integers
- Only booleans
- Strings — e.g. {'port': '8080'}, not {'port': 8080}
Answer: Strings — e.g. {'port': '8080'}, not {'port': 8080}. configparser stores text, so non-string values raise TypeError on write; convert back with the typed getters on read.
Which Python 3.11+ stdlib module reads TOML, the richer nested config format?
- configparser
- tomllib
- json
- yaml
Answer: tomllib. tomllib (added in 3.11) reads TOML files such as pyproject.toml, supporting real types and nesting.
Where should secrets and per-deployment values ideally live?
- In a committed INI file
- Hard-coded in source
- In environment variables (os.environ)
Answer: In environment variables (os.environ). The lesson recommends environment variables for secrets, never a committed config file.