Python TOML Configuration — Core Concepts

TOML (Tom’s Obvious Minimal Language) has become Python’s preferred configuration format since the adoption of pyproject.toml as the standard project configuration file. Python 3.11 added tomllib to the standard library, cementing TOML’s role in the Python ecosystem.

Reading TOML

Python 3.11+ (Built-in)

import tomllib

with open("config.toml", "rb") as f:  # Note: binary mode required
    config = tomllib.load(f)

# From a string
config = tomllib.loads("""
[database]
host = "localhost"
port = 5432
""")

tomllib opens files in binary mode because TOML files must be UTF-8 — the module handles decoding internally.

Python 3.10 and Earlier

pip install tomli
import tomli

with open("config.toml", "rb") as f:
    config = tomli.load(f)

tomli is the package that became tomllib in the standard library. The API is identical.

TOML Type Mapping

TOMLPythonExample
Stringstrname = "Alice"
Integerintport = 8080
Floatfloatrate = 3.14
Booleanbooldebug = true
Date/Timedatetimecreated = 2026-03-28T10:00:00Z
Datedatebirthday = 2000-01-15
Timetimealarm = 07:30:00
Arraylisttags = ["python", "toml"]
Tabledict[section]

Unlike YAML, TOML has no implicit type coercion. "true" is always a string, true is always a boolean. This eliminates an entire class of bugs.

TOML Structure

Tables (Sections)

[database]
host = "localhost"
port = 5432

[database.credentials]
user = "admin"
password = "secret"

Becomes:

{
    "database": {
        "host": "localhost",
        "port": 5432,
        "credentials": {
            "user": "admin",
            "password": "secret",
        }
    }
}

Arrays of Tables

[[servers]]
name = "alpha"
ip = "10.0.0.1"

[[servers]]
name = "beta"
ip = "10.0.0.2"

Becomes:

{"servers": [{"name": "alpha", "ip": "10.0.0.1"}, {"name": "beta", "ip": "10.0.0.2"}]}

Inline Tables

point = { x = 1, y = 2 }

Use inline tables for small, simple groupings. Use full tables for anything more than two or three keys.

Writing TOML

tomli-w (Minimal Writer)

pip install tomli-w
import tomli_w

config = {
    "database": {
        "host": "localhost",
        "port": 5432,
    },
    "features": ["auth", "logging"],
}

with open("config.toml", "wb") as f:  # Binary mode
    tomli_w.dump(config, f)

# To string
toml_string = tomli_w.dumps(config)

tomlkit (Round-Trip Preserving)

tomlkit preserves comments, formatting, and ordering:

pip install tomlkit
import tomlkit

with open("pyproject.toml") as f:
    doc = tomlkit.parse(f.read())

# Modify while preserving formatting
doc["project"]["version"] = "2.0.0"

with open("pyproject.toml", "w") as f:
    f.write(tomlkit.dumps(doc))

This is essential for tools that edit pyproject.toml programmatically.

pyproject.toml: Python’s Configuration Hub

The most important TOML file in Python is pyproject.toml:

[project]
name = "mypackage"
version = "1.0.0"
description = "My awesome package"
requires-python = ">=3.11"
dependencies = [
    "httpx>=0.24",
    "pydantic>=2.0",
]

[project.optional-dependencies]
dev = ["pytest", "ruff", "mypy"]

[tool.ruff]
line-length = 88

[tool.pytest.ini_options]
testpaths = ["tests"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

This single file replaces setup.py, setup.cfg, requirements.txt, and tool-specific config files.

TOML vs. Other Config Formats

FeatureTOMLJSONYAMLINI
CommentsYesNoYesYes
Typed valuesYesPartialYes (with gotchas)No
Nested structureYesYesYesLimited
ArraysYesYesYesNo
Stdlib support3.11+YesNoYes
Surprising behaviorMinimalNoneFrequentSome
Multiline stringsYesNoYesNo

Common Misconception

“TOML is just a better INI format.” While TOML looks similar to INI files, it’s a fully specified format with proper types, nested tables, arrays, datetime support, and a formal grammar. INI files have no standard — every parser handles them differently. TOML has exactly one correct way to parse any valid document.

One Thing to Remember

TOML gives you typed configuration with no surprises — use tomllib (3.11+) for reading, tomlkit for editing existing files with preserved formatting, and put your project config in pyproject.toml.

pythontomlconfigurationtext-processingpyproject

See Also

  • Python Csv Processing Learn how Python reads and writes spreadsheet-style CSV files — the universal language of data tables.
  • Python Json Handling See how Python talks to the rest of the internet using JSON — the universal language apps use to share information.
  • Python Template Strings See how Python's Template strings let you fill in blanks safely, like a Mad Libs game that can't go wrong.
  • Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
  • Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.