---
title: "tomllib em Python: como ler arquivos TOML"
url: "https://python.dev.br/blog/tomllib-ler-toml-python/"
markdown_url: "https://python.dev.br/blog/tomllib-ler-toml-python.MD"
description: "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."
date: "2026-10-10"
author: "Equipe Python Dev BR"
---

# 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](/blog/uv-gerenciador-pacotes-python/), Poetry e [Ruff](/blog/ruff-linter-formatador-python/). 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](https://packaging.python.org/en/latest/specifications/pyproject-toml/) 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](/blog/gerenciadores-de-pacotes-python/), já lida com TOML todos os dias — inclusive com o novo [lockfile padronizado pylock.toml](/blog/pylock-toml-python-lockfile-padrao/).

## 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:

```python
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:

```python
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:

```toml
[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:

```python
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`:

```python
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 = ["diego@exemplo.com.br"]
"""

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:

```python
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](/blog/trabalhando-com-json-python/) exigem.

## Tratamento de erros: TOMLDecodeError

Arquivos com sintaxe inválida geram `tomllib.TOMLDecodeError`. Trate-o como qualquer exceção de parsing:

```python
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](/blog/tratamento-de-erros-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`:

```console
$ pip install tomli-w
```

```python
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](/guias/configurando-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:

```python
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](/glossario/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](/blog/python-dotenv-env-vars-config/) e [pydantic-settings](/blog/pydantic-settings-configuracao-python/).

## 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:

```python
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](/blog/python-pathlib-manipulacao-caminhos-arquivos/) 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](/blog/automatizacao-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.
