tomllib em Python: como ler arquivos TOML
Aprenda a ler arquivos TOML em Python com o módulo tomllib da biblioteca padrão: pyproject.toml, configurações, datas nativas, erros e tomli-w para escrever.
O módulo tomllib do Python lê arquivos TOML — incluindo o pyproject.toml que virou padrão de projeto — direto da biblioteca padrão, sem instalar nada, a partir do Python 3.11. Ele é a escolha certa para ler configurações, metadados de projetos e arquivos gerados por ferramentas como uv, Poetry e Ruff. A limitação importante: tomllib só faz leitura; para escrever TOML você precisa da biblioteca externa tomli-w.
A regra prática é: tomllib.load(arquivo_binario) para ler um arquivo e tomllib.loads(texto) para ler uma string. O resultado é sempre um dicionário Python comum, com tipos nativos preservados — números continuam int ou float, booleanos continuam bool e datas viram objetos datetime. Este guia mostra o uso completo com exemplos executáveis.
O que é TOML e por que ele importa
TOML (Tom’s Obvious, Minimal Language) é um formato de configuração pensado para ser legível por humanos e fácil de interpretar por máquinas. Ele virou o formato de configuração de facto do ecossistema Python: o pyproject.toml é o padrão oficial para metadados de projetos, e ferramentas como uv, Poetry, Ruff, pytest e mypy guardam suas configurações em seções [tool.*] do mesmo arquivo.
Antes do Python 3.11, ler TOML exigia a dependência externa tomli. Desde então, o parser entrou para a biblioteca padrão com o nome tomllib, e praticamente todo script que precisa inspecionar um projeto Python pode fazer isso sem instalar nada.
Se você trabalha com gerenciadores de pacotes modernos, já lida com TOML todos os dias — inclusive com o novo lockfile padronizado pylock.toml.
Como abrir um arquivo TOML com tomllib
O uso mais comum é ler um arquivo. O detalhe que pega muita gente: o arquivo precisa ser aberto em modo binário ('rb'), não em modo texto:
import tomllib
with open("pyproject.toml", "rb") as f:
dados = tomllib.load(f)
print(dados["project"]["name"])
Se você abrir em modo texto ('r'), o tomllib levanta um TypeError imediato:
import tomllib
try:
with open("pyproject.toml", "r", encoding="utf-8") as f: # modo texto: errado
tomllib.load(f)
except TypeError as erro:
print("TypeError:", erro)
# TypeError: File must be opened in binary mode, e.g. use `open('foo.toml', 'rb')`
Esse requisito existe porque o TOML deve ser UTF-8, e o parser faz o decode ele mesmo.
Exemplo prático: lendo um pyproject.toml
Considere um pyproject.toml de um projeto fictício, o alerta-vagas, um bot que monitora vagas de Python:
[project]
name = "alerta-vagas"
version = "1.4.0"
requires-python = ">=3.11"
dependencies = [
"httpx>=0.27",
"pydantic>=2.7",
]
[project.scripts]
alerta-vagas = "alerta_vagas.cli:main"
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I"]
Ler esse arquivo e navegar pelos dados é só acessar dicionários aninhados:
import tomllib
with open("pyproject.toml", "rb") as f:
dados = tomllib.load(f)
projeto = dados["project"]
print(projeto["name"], projeto["version"]) # alerta-vagas 1.4.0
print(projeto["requires-python"]) # >=3.11
print(len(projeto["dependencies"]), "dependências") # 2 dependências
print(dados["tool"]["ruff"]["line-length"]) # 100
print(dados["tool"]["ruff"]["lint"]["select"]) # ['E', 'F', 'I']
Cada tabela [secao] vira um dicionário, e tabelas como [tool.ruff.lint] viram dicionários dentro de dicionários. Repare que tipos são preservados: line-length vem como int, não como string.
Ler TOML de uma string com loads
Quando o conteúdo TOML está em uma string — comum em testes e em valores embutidos no código — use tomllib.loads:
import tomllib
texto = """
title = "Monitor de preços"
ativo = true
intervalo_segundos = 300
produtos = ["notebook", "monitor", "teclado"]
[servidor]
host = "0.0.0.0"
port = 8080
[servidor.tls]
habilitado = false
[alertas.email]
para = ["[email protected]"]
"""
cfg = tomllib.loads(texto)
print(cfg["title"], cfg["intervalo_segundos"], cfg["produtos"][0])
print(cfg["servidor"]["host"], cfg["servidor"]["port"])
print(cfg["servidor"]["tls"]["habilitado"])
print(type(cfg["servidor"]["port"]).__name__, type(cfg["ativo"]).__name__)
# Monitor de preços 300 notebook
# 0.0.0.0 8080
# False
# int bool
Esse padrão de tabela aninhada ([servidor.tls]) é o que a maioria das ferramentas usa para organizar configurações sem repetir prefixos.
Tipos suportados: TOML para Python
O tomllib converte cada tipo TOML para o equivalente natural em Python:
| Tipo no TOML | Tipo resultante em Python | Exemplo |
|---|---|---|
| String básica | str | nome = "Diego" |
| Inteiro | int | port = 8080 |
| Ponto flutuante | float | imposto = 0.17 |
| Booleano | bool | ativo = true |
| Array | list | tags = ["a", "b"] |
| Tabela | dict | [servidor] |
| Offset date-time | datetime.datetime | 2026-10-10T09:30:00-03:00 |
| Local date | datetime.date | 2026-10-24 |
| Local time | datetime.time | 09:00:00 |
As datas são o diferencial em relação ao JSON: TOML tem tipos de data nativos, e o tomllib já devolve objetos prontos:
import tomllib
pedido = """
data_hora = 2026-10-10T09:30:00-03:00
prazo = 2026-10-24
janela = 09:00:00
"""
doc = tomllib.loads(pedido)
print(doc["data_hora"]) # 2026-10-10 09:30:00-03:00
print(doc["prazo"]) # 2026-10-24
print(doc["janela"]) # 09:00:00
Isso elimina o trabalho manual de parsear strings de data que arquivos JSON exigem.
Tratamento de erros: TOMLDecodeError
Arquivos com sintaxe inválida geram tomllib.TOMLDecodeError. Trate-o como qualquer exceção de parsing:
import tomllib
arquivo_corrompido = """
[tool.exemplo
chave = "valor"
"""
try:
tomllib.loads(arquivo_corrompido)
except tomllib.TOMLDecodeError as erro:
print("Erro de TOML:", erro)
# Erro de TOML: Expected ']' at the end of a table declaration (at line 2, column 14)
A mensagem inclui linha e coluna do problema, o que facilita corrigir arquivos de configuração grandes. Para um tratamento de erros mais amplo em scripts que leem configuração do usuário, combine com o guia de tratamento de erros em Python.
E escrever TOML? tomllib não escreve
O tomllib é deliberadamente somente leitura. Quando você precisa gerar um arquivo TOML a partir de dicionários, a saída padrão é a biblioteca tomli-w:
$ pip install tomli-w
import tomli_w
config = {"tool": {"meu_script": {"retries": 3, "timeout": 30}}}
with open("config.toml", "wb") as f:
tomli_w.dump(config, f)
Para o caso mais comum — o pyproject.toml — a recomendação prática é diferente: deixe as ferramentas gerarem e atualizarem o arquivo por você. O comando uv init cria o pyproject.toml completo, uv add mantém as dependências em dia, e o Poetry faz o mesmo no fluxo dele. Escrever pyproject.toml na mão raramente é necessário.
Python 3.10 ou mais antigo: use tomli
Se o seu script precisa rodar também em versões antigas do Python, o padrão recomendado é o fallback para a tomli, que tem a mesma API:
try:
import tomllib # Python 3.11+
except ModuleNotFoundError: # Python 3.10 ou mais antigo
import tomli as tomllib
with open("pyproject.toml", "rb") as f:
dados = tomllib.load(f)
print("ok", dados["project"]["name"])
Assim o mesmo código funciona em qualquer versão com pip disponível para instalar a tomli quando necessário.
tomllib, JSON ou configparser: quando usar cada um
| Critério | TOML + tomllib | JSON | configparser (INI) |
|---|---|---|---|
| Suporte na stdlib | Sim (Python 3.11+) | Sim | Sim |
| Tipos nativos (datas, números) | Sim | Não (tudo vira string de data) | Limitado |
| Comentários no arquivo | Sim | Não | Sim |
| Aninhamento profundo | Sim (tabelas) | Sim | Fraco |
| Escrita pela stdlib | Não | Sim (json.dump) | Sim |
| Uso típico | pyproject.toml, configs de ferramentas | APIs, troca de dados | Configs legadas simples |
Para arquivos de configuração editados por humanos, TOML costuma ganhar. Para trocar dados entre sistemas, JSON segue sendo o padrão. Segredos e variáveis de ambiente não devem ficar em nenhum desses arquivos — para isso, veja como usar python-dotenv e pydantic-settings.
Projeto prático: relatório de dependências do pyproject.toml
Um uso real e frequente do tomllib: um script de automação que analisa os projetos de uma pasta e resume as dependências declaradas:
import tomllib
from pathlib import Path
def resumir_projeto(caminho: Path) -> str:
with open(caminho, "rb") as f:
dados = tomllib.load(f)
projeto = dados["project"]
deps = projeto.get("dependencies", [])
req = projeto.get("requires-python", "não declarado")
return f"{projeto['name']} v{projeto['version']}: {len(deps)} deps, Python {req}"
for pyproject in sorted(Path(".").glob("*/pyproject.toml")):
print(resumir_projeto(pyproject))
# alerta-vagas v1.4.0: 2 deps, Python >=3.11
Com pathlib para achar os arquivos e tomllib para interpretá-los, o script roda em qualquer máquina com Python 3.11, sem uma única dependência externa — útil para CI, auditorias de projetos e automação de rotinas com Python.
Conclusão
O tomllib remove a última desculpa para não ler TOML em Python: desde a versão 3.11, o parser está na biblioteca padrão, devolve dicionários com tipos nativos (inclusive datas) e reporta erros com linha e coluna. Lembre-se das três regras de ouro: abra o arquivo em modo binário, use loads para strings e conte com a tomli-w quando precisar escrever. Para configurações editadas por pessoas, TOML é hoje a escolha padrão do ecossistema Python — e agora você consegue consumi-lo com zero dependências.