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.