The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Read a TOML filewith path.open('rb') as file: config = tomllib.load(file)View examples
Read a TOML stringconfig = tomllib.loads(source)View examples
Support older Pythontomllib = importlib.import_module('tomllib' if sys.version_info >= (3, 11) else 'tomli')View examples
Parse exact decimal valuesconfig = tomllib.loads(source, parse_float=Decimal)View examples
Read TOML date-time valuesreleased = config['package']['released']View examples
Catch invalid TOMLexcept tomllib.TOMLDecodeError as error: report(error)View examples
Bound untrusted inputif path.stat().st_size > MAX_CONFIG_BYTES: raise ValueError('configuration too large')View examples
Validate a required valueport = require_port(config['server'].get('port'))View examples
Read available INI filesloaded = parser.read(['defaults.ini', 'local.ini'], encoding='utf-8')View examples
Read INI textparser.read_string(source)View examples
Convert an INI integerworkers = parser.getint('service', 'workers')View examples
Convert an INI booleandebug = parser.getboolean('service', 'debug')View examples
Provide a missing-option fallbacktimeout = parser.getfloat('service', 'timeout', fallback=5.0)View examples
Define shared defaultsparser['DEFAULT'] = {'timeout': '5', 'retries': '2'}View examples
Layer configuration filesparser.read(['base.ini', 'deployment.ini', 'local.ini'], encoding='utf-8')View examples
Disable interpolationparser = ConfigParser(interpolation=None)View examples
Use cross-section interpolationparser = ConfigParser(interpolation=ExtendedInterpolation())View examples
Preserve option-name caseparser.optionxform = strView examples
Serialize INI configurationparser.write(file, space_around_delimiters=True)View examples

Configuration is an input boundary, not an untyped global dictionary. Use tomllib when you want the well-defined TOML 1.0 format and native scalar types, or configparser when compatibility with INI-style files matters. Parse bounded input, merge layers in a documented order, convert and validate every required setting, and keep credentials outside files committed to source control. tomllib was added in Python 3.11 and intentionally reads but does not write TOML.

Step by step

Detailed examples

01

Read TOML through the correct text or binary boundary

tomllib.loads accepts str, while tomllib.load requires a readable binary file object so the parser controls TOML's required UTF-8 decoding. The module implements TOML 1.0, returns ordinary Python containers, and was added in Python 3.11 by PEP 680. For Python 3.10 and earlier, declare the compatible tomli backport rather than hiding an optional dependency. The standard library has no tomllib.dump or dumps API; use a dedicated writer when generation or comment-preserving edits are required.

Parse a small nested TOML document
import tomllib

source = '''
title = "Command Memo"

[server]
host = "127.0.0.1"
ports = [8000, 8001]
'''
config = tomllib.loads(source)

print(config['title'])
print(config['server']['host'])
print(config['server']['ports'])
Output
Command Memo
127.0.0.1
[8000, 8001]
Back to quick reference ↑
02

Understand TOML's typed conversion rules

TOML strings, integers, floats, booleans, arrays, and tables become the corresponding Python primitives and containers. Offset date-times become aware datetime objects with a fixed datetime.timezone offset, while local date-times remain naive; dates and times use their matching datetime types. parse_float receives the original float token and can construct Decimal for exact decimal input. Its result cannot be a dict or list. Conversion supplies representation, not business validation, so ranges and relationships still need explicit checks.

Preserve a decimal token and inspect temporal types
from decimal import Decimal
from datetime import date, datetime
import tomllib

source = '''
price = 19.95
released = 2026-08-12
generated = 2026-08-12T15:30:00Z
'''
config = tomllib.loads(source, parse_float=Decimal)

print(config['price'], type(config['price']).__name__)
print(config['released'].isoformat(), isinstance(config['released'], date))
print(config['generated'].isoformat(), isinstance(config['generated'], datetime))
Output
19.95 Decimal
2026-08-12 True
2026-08-12T15:30:00+00:00 True
Back to quick reference ↑
03

Treat parsed configuration as untrusted input

Parsing confirms format, not application correctness. Catch TOMLDecodeError at the configuration boundary, attach the source name to diagnostics, then validate required keys, types, ranges, mutually exclusive options, and unknown fields before starting dependent services. Python 3.14 added documented msg, doc, pos, lineno, and colno attributes to TOMLDecodeError; do not rely on those attributes when supporting older runtimes. The Python documentation also recommends limiting the size of untrusted TOML because malicious input can consume considerable CPU or memory.

Validate a parsed port with a clear error
import tomllib

def require_port(value):
    if isinstance(value, bool) or not isinstance(value, int):
        raise TypeError('server.port must be an integer')
    if not 1 <= value <= 65535:
        raise ValueError('server.port must be between 1 and 65535')
    return value

for source in ('[server]\nport = 8443', '[server]\nport = 70000'):
    try:
        port = require_port(tomllib.loads(source)['server']['port'])
        print(f'accepted {port}')
    except (KeyError, TypeError, ValueError, tomllib.TOMLDecodeError) as error:
        print(type(error).__name__, str(error))
Output
accepted 8443
ValueError server.port must be between 1 and 65535
Back to quick reference ↑
04

Use explicit converters for INI values

configparser supports a family of INI-like dialects rather than one universal INI standard. It stores values as strings and lowercases option names by default; section names remain case-sensitive. Use getint, getfloat, and getboolean instead of ad hoc casts, especially because bool('false') is true. A ConfigParser is strict by default, rejecting duplicate sections or options within one source. read silently skips unavailable files and reports those it loaded, whereas read_file and read_string surface their input directly.

Read typed options from INI text
from configparser import ConfigParser

source = '''
[service]
workers = 4
debug = no
ratio = 0.75
'''
parser = ConfigParser()
parser.read_string(source)

print(parser.getint('service', 'workers') + 1)
print(parser.getboolean('service', 'debug'))
print(parser.getfloat('service', 'ratio'))
print(list(parser['service']))
Output
5
False
0.75
['workers', 'debug', 'ratio']
Back to quick reference ↑
05

Define deterministic precedence for defaults and overrides

Values in the special DEFAULT section are visible from every ordinary section and have precedence over a fallback argument. Reading multiple sources merges them in order: a later value replaces an earlier conflict, while unrelated earlier settings remain. This is useful for a documented chain such as built-in defaults, system file, deployment file, then an explicitly selected local file. Avoid silently reading an unbounded working-directory file, and distinguish an absent option from an invalid present option because fallback does not suppress conversion errors.

Layer an override over application defaults
from configparser import ConfigParser

base = '''
[DEFAULT]
timeout = 5

[service]
host = api.internal
workers = 2
'''
override = '''
[service]
workers = 6
'''
parser = ConfigParser()
parser.read_string(base, source='base.ini')
parser.read_string(override, source='deployment.ini')

print(parser['service']['host'])
print(parser.getint('service', 'workers'))
print(parser.getint('service', 'timeout', fallback=30))
print(parser.get('service', 'region', fallback='local'))
Output
api.internal
6
5
local
Back to quick reference ↑
06

Choose interpolation and serialization behavior deliberately

ConfigParser uses BasicInterpolation by default, expanding %(name)s references from the current section or DEFAULT section. ExtendedInterpolation enables ${section:option} references, and interpolation=None preserves values literally—often the safest choice for arbitrary percent signs, templates, or opaque credentials. Interpolation happens when values are read and can raise errors then. Set optionxform = str before reading only when case-sensitive keys are a format requirement. write serializes current data but does not round-trip comments, delimiter choices, or original formatting.

Resolve a cross-section path and preserve a literal percent
from configparser import ConfigParser, ExtendedInterpolation

source = '''
[paths]
root = /srv/app

[logs]
directory = ${paths:root}/logs
'''
expanded = ConfigParser(interpolation=ExtendedInterpolation())
expanded.read_string(source)
literal = ConfigParser(interpolation=None)
literal.read_string('[message]\nprogress = 75% complete')

print(expanded['logs']['directory'])
print(literal['message']['progress'])
expanded['logs']['level'] = 'INFO'
print(expanded.get('logs', 'level'))
Output
/srv/app/logs
75% complete
INFO
Back to quick reference ↑

Local code tester

Parse and validate application configuration

Experiment with typed TOML values and a small validation boundary using only deterministic standard-library behavior.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software Foundationtomllib — Parse TOML filesdocs.python.org
  2. Python Software Foundationconfigparser — Configuration file parserdocs.python.org
  3. Python Software FoundationPEP 680 — tomllib: Support for Parsing TOML in the Standard Librarypeps.python.org
  4. TOMLTOML v1.0.0 Specificationtoml.io

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback