Read INI Settings with configparser
Parse a small INI configuration and return typed, validated job settings.
Example check: Worked and guided code samples are checked against CPython 3.13. Practice uses Pyodide 0.29.5 (Python 3.13) in your browser. How we check lessons
Video lesson: Read INI Settings with configparser
The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube
Jump to a chapter
Read the video transcript
Select a timestamp to watch that moment on YouTube.
- 00:00
A little configuration file can make a script easier to operate. Instead of editing the script every time, a person changes retry count or an enabled flag in an INI file. Python's configparser can read this familiar section-and-option format. But the file contains text, even when a value looks like a number or a Boolean. An application that needs an integer retry count and a real Boolean must request those types and validate them. In this lesson, we will build a function that reads one job section from an in- memory string, so everything runs inside the browser console without opening a file.
- 00:40
First we will reproduce an unexpected failure with a percent sign. ConfigParser's default interpolation treats percent syntax specially, so ordinary-looking status text such as one hundred percent ready can raise an error on retrieval. Then we will decide to disable interpolation, use getint and getboolean, and enforce a retry range from zero through ten. At the end we will test no, zero, a malformed value, and an out-of-range value. The purpose is a small, explicit configuration contract, not a general secret-management system. The read_string call succeeds, and the error appears when we retrieve the option.
- 01:21
Default interpolation sees a percent sign and expects its own special syntax. Our status text is not trying to reference another setting; it is simply a literal percentage. Catching Exception is convenient for this short demonstration because it lets the video show the exception name, but it is too broad for the finished function. The final function will catch documented configuration errors and value conversion errors instead. We have a design choice: if our configuration intentionally used interpolation, we would need to write values according to that feature's rules. For this simple job format, we want literal text, so ConfigParser with
- 02:02
interpolation=None is clearer. This is not a statement that percent signs are generally invalid in INI files. It is a statement about what the parser is configured to do when values are fetched. Before changing the parser, we should inspect the basic type problem too. The file's retries equals three is stored as text. If we add one to the raw string, Python does not magically convert it. The parser supplies explicit typed getters for that purpose. The first line confirms the raw option is a string. getint converts the retry count to an integer, and getboolean recognizes yes as True.
- 02:42
The percent-bearing status now comes back literally because interpolation is disabled. We have separated three ideas that are easy to conflate: parsing the INI structure, converting a particular option's type, and validating whether that value is allowed for our job. getint knows how to convert a numeric text value, but it does not know that our application allows only zero through ten retries. We must check that range ourselves. Similarly, getboolean recognizes common true and false spellings, but an arbitrary word such as maybe will not become a valid Boolean. Avoid bool on a nonempty string: bool('no') is True, which is the opposite
- 03:22
of the intended meaning. The format also requires the job section and both named options. The finished function should produce one predictable failure when they are missing or malformed. That makes the checked task easier to understand and prevents a half-populated settings object from leaking into the rest of a program. We will now implement that small contract. The function creates a fresh parser for this input, so calls do not share configuration state. It reads the text, asks for two typed values, and checks that retries falls within the allowed range. Only after those steps succeed does it return the dictionary.
- 04:04
The try block covers parsing, missing sections or options, failed type conversion, and our range error. The except block deliberately translates those failures into one ValueError with the message invalid job settings. The from None suppresses a duplicate low- level traceback in this teaching example. In a real application, an administrator- facing tool might preserve a more specific diagnostic, but the key design still holds: invalid configuration should fail early with a clear contract. Notice also that we do not log or print the raw configuration string inside the function. That matters if a future configuration contains information you do not want to
- 04:46
expose. Our sample is harmless, but public repositories should not contain real API keys or passwords. A production design would consider defaults, file location, and secret storage separately. Here we focus on the type and validation pipeline you can reproduce in any Python console. Let us probe the boundary values before trusting it. Zero retries is within our allowed range, and no becomes a real False rather than a truthy nonempty string. The extra status value contains a percent sign but causes no interpolation problem. The next two inputs fail for different reasons: eleven is a valid integer that
- 05:30
violates our application range, while the last string omits the enabled option. Both produce the same public error message promised by the function. You can add malformed numbers or enabled equals maybe as further tests. Before writing another configuration parser, decide which options are required, which types they need, what range of values makes sense, and whether interpolation should be enabled. Those choices are part of the application, not guesses the INI file can make for us. On the lesson page, the starter function returns an empty dictionary. Fill in the parser, conversions, range check, and error handling, then run the checked task.
- 06:12
After it passes, change the sample to an invalid case and predict the result before you execute it. One final reminder: sample configuration belongs in a tutorial, but credentials do not belong in a public repository. Choose an appropriate secret-handling method for real deployments.
Understand the concept
INI is a compact format for named sections and key–value options. configparser.ConfigParser reads it from files or strings; the browser exercise uses read_string so no filesystem is needed. Values begin as text. A setting that looks like 3 is not an integer until you call getint or convert it. A setting such as yes can become a Boolean through getboolean, which recognizes several common true and false spellings.
The checked task reads a [job] section with retries and enabled options. It returns a dictionary containing an integer retries and a Boolean enabled. Validate retries as a value from zero through ten; missing sections, malformed numbers, and unsupported Boolean words should produce a single clear ValueError. The prepared example should yield {'retries': 3, 'enabled': True}. Run cases with zero retries, enabled=no, and an invalid number.
By default ConfigParser interpolates percent expressions in values. That is useful when you intentionally reference another option, but a lone percent sign such as 100% ready can raise an interpolation error when the value is retrieved. This lesson turns interpolation off with ConfigParser(interpolation=None), so text stays literal. That makes the tutorial's configuration behavior easier to reason about. It does not silently grant a setting trust; validate every option before using it.
A configuration file can still contain sensitive values. Do not commit real API keys or passwords to a public repository. Keep the sample string in this tutorial harmless. For an application, decide where configuration lives, how to handle missing files and defaults, and whether environment variables or a secret manager are more appropriate for secrets. ConfigParser is useful when a simple human-readable INI file fits the job, but its text syntax is not a schema or a security boundary.
- ConfigParser reads INI sections and options
- getint and getboolean convert text to specific types
- interpolation=None keeps a percent sign literal
- Validate missing, malformed, and out-of-range settings
See it step by step
Read the code, predict the output, then compare it with the result.
01. Read typed options
from configparser import ConfigParser
parser = ConfigParser(interpolation=None)
parser.read_string("[job]\nretries = 3\nenabled = yes\n")
print(parser.getint("job", "retries"))
print(parser.getboolean("job", "enabled"))3
TrueThe getters convert stored text to the types the application actually needs.
02. Keep a percent sign literal
from configparser import ConfigParser
parser = ConfigParser(interpolation=None)
parser.read_string("[job]\nstatus = 100% ready\n")
print(parser.get("job", "status"))100% readyDisabling interpolation prevents a plain percent sign from being treated as interpolation syntax.
03. Recognize an invalid integer
from configparser import ConfigParser
parser = ConfigParser(interpolation=None)
parser.read_string("[job]\nretries = many\n")
try:
parser.getint("job", "retries")
except ValueError:
print("retries must be an integer")retries must be an integerConfiguration values need explicit conversion and useful failure handling.
A closer look
Follow the reasoning, inspect each result, then try the suggested changes in the console below.
Read a section and convert its text values
INI configuration groups options under named sections. ConfigParser.read_string accepts an INI string, which makes the lesson independent of files and compatible with a browser console. Each option is fundamentally textual. Printing parser.get for retries shows a string, not an int, even though the file spells it with a digit. A program that needs arithmetic must request a typed value or convert it explicitly.
Use getint for retries and getboolean for enabled. The Boolean getter understands common values such as yes and no; it is more deliberate than bool('no'), which would return True because the string is nonempty. The task will also validate a numeric range after conversion. A parser can identify the shape of INI input, but the application must decide which values are acceptable for its operation.
from configparser import ConfigParser
parser = ConfigParser(interpolation=None)
parser.read_string("[job]\nretries = 3\nenabled = yes\n")
print(type(parser.get("job", "retries")).__name__)
print(parser.getint("job", "retries"))
print(parser.getboolean("job", "enabled"))str
3
True- Observe that the raw retrieved value has type str.
- Use typed getters before applying numeric or Boolean logic.
Disable unwanted interpolation and validate the job
Default ConfigParser interpolation treats a percent sign as special syntax. A value such as 100% ready can therefore fail when retrieved, even though it looks like ordinary status text. This tutorial turns interpolation off so a percent sign remains literal. It is an explicit configuration choice, not a workaround for an unrelated parse error. The same parser still supports typed getters for the two job options.
The function catches configparser.Error for missing sections, missing options, and parse failures, as well as ValueError for failed conversion and range checks. It raises one clear ValueError for invalid job settings. An application might instead expose finer error details to an administrator, but a consistent error makes this small task easy to test. Keep the harmless example data separate from real secrets that should not be checked into a public repository.
import configparser
def load_job_settings(text):
parser = configparser.ConfigParser(interpolation=None)
try:
parser.read_string(text)
retries = parser.getint("job", "retries")
enabled = parser.getboolean("job", "enabled")
if not 0 <= retries <= 10:
raise ValueError("range")
except (configparser.Error, ValueError):
raise ValueError("invalid job settings") from None
return {"retries": retries, "enabled": enabled}
print(load_job_settings("[job]\nretries=3\nenabled=yes\n")){'retries': 3, 'enabled': True}- Trace read_string, type conversion, and range validation in order.
- Observe the final dictionary contains int and bool rather than source text.
Verify percent text, false values, and failures
The first check reads a literal percent-bearing status without triggering interpolation. The second reads no as False and zero as a valid retry count. Those cases demonstrate two decisions independent of each other: whether percent syntax is interpreted, and how a specific job option is converted. Adding an unrelated status option does not change the function's return shape, because the function only asks for the two options in its contract.
A negative or oversized retry count is still an integer, but it violates the application range. A missing enabled option or malformed integer also needs a predictable failure. Test one invalid case explicitly and catch its ValueError. This is more useful than relying on the parser to enforce business rules it does not know. In a real deployment, avoid printing configuration that contains secrets and decide whether defaults should be allowed rather than silently assuming them.
import configparser
def load_job_settings(text):
p = configparser.ConfigParser(interpolation=None)
try:
p.read_string(text)
retries = p.getint("job", "retries")
enabled = p.getboolean("job", "enabled")
if not 0 <= retries <= 10:
raise ValueError()
except (configparser.Error, ValueError):
raise ValueError("invalid job settings") from None
return {"retries": retries, "enabled": enabled}
print(load_job_settings("[job]\nretries=0\nenabled=no\nstatus=100% ready\n"))
try:
load_job_settings("[job]\nretries=11\nenabled=yes\n")
except ValueError as error:
print(error){'retries': 0, 'enabled': False}
invalid job settings- Confirm the literal percent text causes no interpolation error.
- Separate successful type conversion from the later application range check.
Try it in Python
Edit the example and run it. Python starts in your browser the first time you click Run.
Python console
Ready to runNeed input()? Add one value per line
Your output appears here.
Need a hint?
Put parser.read_string and both getters in a try block. Check 0 <= retries <= 10; if false, raise ValueError. Catch (configparser.Error, ValueError) and raise ValueError('invalid job settings') from None. Return the typed dictionary after validation.
Complete the task and select Check task to verify your code.
Quick quiz
Three questions. You can change your answers and try again.
Typical mistakes
Everyone meets these errors. See what causes them and how to fix them.
Treating retrieved text as an integer
from configparser import ConfigParser
p=ConfigParser(); p.read_string('[job]\nretries=3\n')
print(p.get('job','retries') + 1)from configparser import ConfigParser
p=ConfigParser(); p.read_string('[job]\nretries=3\n')
print(p.getint('job','retries') + 1)What happens: A string and integer cannot be added; the operation raises TypeError.
Use getint and validate the resulting number.
Assuming every percent is interpolation syntax
from configparser import ConfigParser
p=ConfigParser(); p.read_string('[job]\nstatus=100% ready\n'); print(p.get('job','status'))from configparser import ConfigParser
p=ConfigParser(interpolation=None); p.read_string('[job]\nstatus=100% ready\n'); print(p.get('job','status'))What happens: A lone percent sign raises InterpolationSyntaxError with default interpolation.
Turn off interpolation when configuration values should be literal.