LESSON 108 · DEEPER PYTHON30 min

Read TOML Configuration with Python tomllib

Load a TOML configuration string and validate a required positive integer setting.

Before you start: Dictionaries · Exceptions · Functions

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 TOML Configuration with Python tomllib

The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube

Read the video transcript

Select a timestamp to watch that moment on YouTube.

  1. 00:00

    This TOML file says retry, but the program asks for retries. Run it now. The KeyError will show where parsing ends and application validation must begin. The terminal points at config service retries and raises KeyError. tomllib did its job: it parsed a table containing retry equal to four. The typo is in the application's lookup. Silently replacing a missing required field with a default would let the service start with a value nobody supplied. A configuration typo can be harder to spot than a syntax error because the document still parses cleanly. An operator might see a service section and a number four and assume the

  2. 00:42

    application will use it. This run demonstrates why tests should exercise the actual field lookup, not merely assert that tomllib loads the file. A required setting should have a named validation error and, if appropriate, a policy for unknown keys. That policy matters when a file contains both the correct plural field and an older singular spelling: ignoring the extra name could hide a stale setting. The diagnosis prints the nested service dictionary and then retries present: False. Seeing retry singular beside that False identifies the mismatch before changing code. TOML parsing checks syntax, not whether this service has the fields we require.

  3. 01:27

    A boolean is also an integer subclass in Python, so our retry validator rejects bool explicitly. The printed mapping exposes the singular key and the missing plural key. Syntax-valid TOML can violate other schema rules too: retries = 4.0 parses as a float, and retries = "4" parses as text, though both look like a four in a configuration review. A service table can even be replaced by a scalar, changing the shape the loader expects. Validation therefore needs rules for presence, type, and allowed range after parsing. The diagnostic print is safe here only because the sample contains no

  4. 02:07

    credentials. A production error should name the relevant field without logging an entire config, where neighboring entries could contain tokens. If multiple configuration files are merged, report which source supplied the invalid value so an operator can correct the right file. The fixed loader reads the document with tomllib.loads, requires service to be a table, and validates retries as a positive non-boolean integer. The terminal prints four for a valid file. A binary file object could instead go to tomllib.load. There is no tomllib.dump for writing the updated configuration back.

  5. 02:48

    The loader should check that service is a TOML table, represented here by a Python dictionary, before reading retries. A missing service name or a scalar service value then takes a controlled ValueError path instead of an accidental lookup or type error. Once the table is established, service dot get returns None for a missing retries key. The exact integer check then rejects that None with the lesson's invalid-retries ValueError. The error text distinguishes a malformed table from a missing or invalid count; no KeyError escapes to the caller. Exact integer checking excludes booleans; positivity excludes zero and negatives.

  6. 03:30

    A production retry policy may also cap the count, perhaps at five, to avoid a cascade of network calls during exponential backoff. Put that ceiling beside the other schema rules and test it. The binary-file requirement is observable too: tomllib.load given io.StringIO raises TypeError, while io.BytesIO with the same TOML bytes succeeds. Read a real file in binary mode so the parser handles the TOML UTF-8 encoding. If the application already has decoded text, use loads. File encoding failures, malformed TOML syntax, and application schema failures are different diagnostics.

  7. 04:13

    The verifier tries a misspelled key, a nonpositive count, and a scalar service field. Each raises our deliberate ValueError rather than an accidental KeyError, TypeError, or quiet fallback. When this lesson uses a sample config string, it contains no credentials; a real service should avoid printing its full parsed configuration in logs. A useful validation matrix includes retries equal to four as a success, plus zero, true, float four, a misspelled key, a missing service table, and a scalar service value as failures. The last case can be written as service equals a quoted word at the document root:

  8. 04:53

    it is legal TOML but not a nested table. It should now raise the lesson's ValueError rather than a Python TypeError. Those are schema errors after successful parsing; a malformed quote or table header instead raises TOMLDecodeError before the validator runs. Also decide whether unknown keys are rejected. A strict check can subtract an allowed set such as retries and host from the keys under service. If retry remains, report it even when retries is present, so a stale spelling cannot hide in an otherwise valid deployment. When optional fields change, update that allowed set and its tests together.

Understand the concept

A small tool reads a configuration containing a service name and a retry count. TOML tables become nested dictionaries in Python, so a program can access values without inventing its own parser. Python 3.11 and later include tomllib for reading TOML; this lesson uses text held in memory so the console needs no local config file.

The browser starter prints 4 for its valid sample, but its fallback default silently accepts a missing or misspelled required retries key. In the video's separate broken demo, indexing that missing key raises KeyError. A successfully parsed TOML document can still violate application rules, such as retries being zero, a string instead of an integer, or service being a scalar instead of a table. Parsing and semantic validation are separate steps.

Print the parsed mapping before reading individual settings. First confirm service is a table, represented by a dictionary, before accessing retries. Inspect whether retries is an int, and remember that bool is a subclass of int in Python; for this particular contract, a boolean is not a valid retry count. Decide which fields are required and which have documented defaults. Use tomllib.loads for a text string and tomllib.load for a binary file object. After parsing, validate required tables and values explicitly; raise ValueError with a useful message when the contract is not met. tomllib does not write TOML, so do not assume a dumps method exists.

An invalid TOML document raises TOMLDecodeError before any application validation runs. A missing or non-table service value, or a nonpositive retry count, should fail with the lesson's own ValueError. The final run checks a valid configuration and a typo in the required field. Configuration may contain secrets; avoid printing complete parsed dictionaries in production logs. The classroom string contains public sample settings only. Keep the distinction between syntax errors, missing settings and invalid values clear to a caller who must fix a configuration file.

  • A small tool reads a configuration containing a service name and a retry count.
  • Indexing a missing nested key raises KeyError, while blindly using get with a default can hide a typo in a required setting.
  • Use tomllib.loads for a text string and tomllib.load for a binary file object.
  • An invalid TOML document raises TOMLDecodeError before any application validation runs.

See it step by step

Read the code, predict the output, then compare it with the result.

01. Read a nested table

PYTHON
import tomllib
config = tomllib.loads('[service]\nname = "demo"\nretries = 4\n')
print(config['service']['name'])
print(config['service']['retries'])
EXPECTED OUTPUT
demo
4

TOML table entries appear under the service dictionary key.

02. Check a required value

PYTHON
import tomllib
value = tomllib.loads('[service]\nretries = 4\n')['service']['retries']
print(type(value) is int and value > 0)
EXPECTED OUTPUT
True

The application rule checks both type and range after syntax parsing succeeds.

03. Catch invalid TOML syntax

PYTHON
import tomllib
try:
    tomllib.loads('[service\nretries = 4')
except tomllib.TOMLDecodeError:
    print('invalid TOML')
EXPECTED OUTPUT
invalid TOML

A syntax error fails during parsing, before any business rule is checked.

A closer look

Follow the reasoning, inspect each result, then try the suggested changes in the console below.

01 / 03

Observe the first result

A small tool reads a configuration containing a service name and a retry count. TOML tables become nested dictionaries in Python, so a program can access values without inventing its own parser. Python 3.11 and later include tomllib for reading TOML; this lesson uses text held in memory so the console needs no local config file.

TOML table entries appear under the service dictionary key. Print the parsed mapping before reading individual settings. Inspect whether retries is an int, and remember that bool is a subclass of int in Python; for this particular contract, a boolean is not a valid retry count. Decide which fields are required and which have documented defaults.

PYTHON
import tomllib
config = tomllib.loads('[service]\nname = "demo"\nretries = 4\n')
print(config['service']['name'])
print(config['service']['retries'])
EXPECTED OUTPUT
demo
4
Follow the reasoning
  1. Predict the first sample's printed value and type.
  2. Run it, then compare with the expected output.
02 / 03

Change the rule deliberately

The browser starter prints 4 for its valid sample, but its fallback default silently accepts a missing or misspelled required retries key. In the video's separate broken demo, indexing that missing key raises KeyError. A successfully parsed TOML document can still violate application rules, such as retries being zero, a string instead of an integer, or service being a scalar instead of a table. Parsing and semantic validation are separate steps.

The application rule checks both type and range after syntax parsing succeeds. Use tomllib.loads for a text string and tomllib.load for a binary file object. After parsing, validate required tables and values explicitly; raise ValueError with a useful message when the contract is not met. tomllib does not write TOML, so do not assume a dumps method exists. Parse with tomllib.loads, require service to be a dictionary, then check type(retries) is int and retries > 0. Raise ValueError for a missing or invalid table or count.

PYTHON
import tomllib
value = tomllib.loads('[service]\nretries = 4\n')['service']['retries']
print(type(value) is int and value > 0)
EXPECTED OUTPUT
True
Follow the reasoning
  1. Identify the line that changes the rule.
  2. Run the corrected sample with the same input.
03 / 03

Verify the boundary

Print the parsed mapping before reading individual settings. First confirm service is a table, represented by a dictionary, before accessing retries. Inspect whether retries is an int, and remember that bool is a subclass of int in Python; for this particular contract, a boolean is not a valid retry count. Decide which fields are required and which have documented defaults. Use tomllib.loads for a text string and tomllib.load for a binary file object. After parsing, validate required tables and values explicitly; raise ValueError with a useful message when the contract is not met. tomllib does not write TOML, so do not assume a dumps method exists.

A syntax error fails during parsing, before any business rule is checked. An invalid TOML document raises TOMLDecodeError before any application validation runs. A missing or non-table service value, or a nonpositive retry count, should fail with the lesson's own ValueError. The final run checks a valid configuration and a typo in the required field. Configuration may contain secrets; avoid printing complete parsed dictionaries in production logs. The classroom string contains public sample settings only. Keep the distinction between syntax errors, missing settings and invalid values clear to a caller who must fix a configuration file.

PYTHON
import tomllib
try:
    tomllib.loads('[service\nretries = 4')
except tomllib.TOMLDecodeError:
    print('invalid TOML')
EXPECTED OUTPUT
invalid TOML
Follow the reasoning
  1. Try the documented edge case.
  2. Explain why the output satisfies the function contract.

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 run
Need input()? Add one value per line
Ctrl / ⌘ + Enter to run
OUTPUT
Your output appears here.
Your turnMake retry_count(text) require [service].retries to be a positive non-boolean integer. Return it for valid TOML; raise ValueError for a missing or invalid value. The prepared call prints 4.
Need a hint?

Parse with tomllib.loads. Require service to be a dictionary, then check type(retries) is int and retries > 0; raise ValueError for a missing or invalid table or count.

Complete the task and select Check task to verify your code.

    Quick quiz

    Three questions. You can change your answers and try again.

    01.Which function parses TOML text in memory?

    02.Does valid TOML syntax guarantee valid application settings?

    03.Why use type(value) is int for this count?

    Typical mistakes

    Everyone meets these errors. See what causes them and how to fix them.

    The visible failure

    COMMON MISTAKE
    config['service']['retry']
    FIX
    validate config['service']['retries'] after parsing

    What happens: Indexing a missing nested key raises KeyError, while blindly using get with a default can hide a typo in a required setting.
    Use tomllib.loads for a text string and tomllib.load for a binary file object. After parsing, validate required tables and values explicitly; raise ValueError with a useful message when the contract is not met. tomllib does not write TOML, so do not assume a dumps method exists.

    Missing the edge condition

    COMMON MISTAKE
    return config.get('service', {}).get('retries', 3)
    FIX
    raise ValueError when required retries is missing or invalid

    What happens: An invalid TOML document raises TOMLDecodeError before any application validation runs.
    Configuration may contain secrets; avoid printing complete parsed dictionaries in production logs. The classroom string contains public sample settings only. Keep the distinction between syntax errors, missing settings and invalid values clear to a caller who must fix a configuration file.

    Browse this lesson’s problem fixes

    Sources and further reading