Arquivos de configuração ajudam a separar decisões operacionais do código-fonte. Em vez de alterar uma constante e publicar uma nova versão do programa sempre que uma porta, um caminho ou uma opção muda, você pode registrar esses valores em um arquivo externo. O formato TOML ganhou espaço nesse cenário porque combina leitura simples, tipos claros e uma estrutura que se transforma naturalmente em dicionários. Desde o Python 3.11, a biblioteca padrão inclui o módulo tomllib, que lê TOML sem exigir instalação adicional.
Neste guia, você aprenderá a usar tomllib no Python para carregar arquivos, acessar tabelas, interpretar datas, personalizar números decimais, validar campos obrigatórios e tratar arquivos inválidos. Também veremos como essa abordagem se conecta ao pyproject.toml, usado por ferramentas modernas de empacotamento, lint e testes. Caso você esteja estruturando um projeto maior, vale revisar o artigo sobre dependências com Poetry e o tutorial para criar um pacote Python instalável.
O que é TOML e por que usá-lo?
TOML significa “Tom’s Obvious, Minimal Language”. A proposta é oferecer um formato de configuração legível por pessoas e fácil de converter para estruturas de dados. Um documento TOML usa pares de chave e valor, tabelas, arrays e tipos como números, booleanos, datas e horários. Diferentemente de formatos que tratam quase tudo como texto, TOML preserva tipos importantes durante a leitura.
app_name = "Painel de vendas"
debug = false
port = 8080
[database]
host = "localhost"
name = "vendas"
timeout = 5.5
[features]
reports = true
exports = ["csv", "xlsx"]Esse arquivo descreve uma aplicação, uma conexão de banco e alguns recursos. Ao ser carregado pelo Python, ele vira um dicionário aninhado. A especificação oficial do formato está disponível no site do TOML 1.0. Ela é útil para conferir regras de strings, tabelas, arrays, datas e nomes de chaves.
Quando usar tomllib
O tomllib é indicado quando seu programa precisa ler TOML. Ele não grava nem edita arquivos. Essa distinção é importante: para um serviço que carrega configurações no início, o módulo padrão é suficiente. Para um editor que precisa preservar comentários, ordem e formatação, considere uma biblioteca voltada a escrita e edição.
O módulo está disponível a partir do Python 3.11. Em versões anteriores, o pacote tomli oferece uma API semelhante. Antes de decidir a compatibilidade, confira a versão mínima suportada pelo projeto. Em projetos novos, você pode registrar essa exigência no pyproject.toml. O artigo sobre Ruff no Python mostra outro uso prático desse mesmo arquivo para centralizar configurações de ferramentas.
Como ler um arquivo TOML
Crie um arquivo chamado config.toml com o conteúdo do primeiro exemplo. Em seguida, abra-o em modo binário e use tomllib.load:
import tomllib
with open("config.toml", "rb") as arquivo:
config = tomllib.load(arquivo)
print(config["app_name"])
print(config["database"]["host"])
print(config["features"]["exports"])O modo rb é obrigatório para load. Essa decisão evita ambiguidades de codificação e segue a API documentada oficialmente. A documentação do tomllib detalha as funções, exceções e a conversão entre tipos TOML e Python.
O resultado é um dicionário comum. Strings viram str, inteiros viram int, números decimais viram float, arrays viram listas e tabelas viram dicionários. Isso permite usar as mesmas técnicas de acesso e validação aplicadas a dados JSON.
Lendo TOML a partir de uma string
Quando o conteúdo já está na memória, use tomllib.loads. Diferentemente de load, essa função recebe uma string:
import tomllib
texto = """
name = "worker"
workers = 4
active = true
"""
config = tomllib.loads(texto)
print(config)Esse método é útil em testes, em configurações recebidas de um serviço ou quando o arquivo foi obtido por outro componente. Mesmo assim, limite o tamanho de entradas não confiáveis. Um arquivo malicioso pode consumir recursos excessivos durante a análise.
Como acessar valores com segurança
Usar colchetes é apropriado quando a chave é obrigatória. Se ela não existir, o Python gera KeyError, o que pode ser desejável para impedir que a aplicação inicie com configuração incompleta. Para campos opcionais, use get com um valor padrão:
debug = config.get("debug", False)
log_level = config.get("log_level", "INFO")
timeout = config.get("database", {}).get("timeout", 10)Evite esconder erros importantes com padrões em excesso. Uma senha, um endereço de banco ou uma chave de ambiente não deveria assumir silenciosamente um valor incorreto. Separe campos obrigatórios de opcionais e produza mensagens claras quando algo estiver faltando.
Validando configurações depois da leitura
O tomllib verifica a sintaxe TOML, mas não conhece as regras do seu sistema. Ele aceitará uma porta negativa, um texto vazio ou um nome de ambiente desconhecido se esses valores forem sintaticamente válidos. Portanto, adicione validação de domínio após carregar o arquivo.
def validar_config(config: dict) -> None:
obrigatorias = ["app_name", "database"]
ausentes = [chave for chave in obrigatorias if chave not in config]
if ausentes:
raise ValueError(f"Chaves ausentes: {', '.join(ausentes)}")
porta = config.get("port", 8080)
if not 1 <= porta <= 65535:
raise ValueError("A porta deve estar entre 1 e 65535")
if not config["database"].get("host"):
raise ValueError("database.host é obrigatório")Para projetos com muitos campos, modelos de validação podem reduzir código repetitivo. Mesmo sem uma biblioteca adicional, funções pequenas e testes automatizados já evitam que uma configuração inválida chegue à produção.
Tratando erros de sintaxe
Quando o documento viola a especificação, o módulo gera tomllib.TOMLDecodeError. Capture essa exceção perto da fronteira de leitura e apresente uma mensagem útil:
import tomllib
from pathlib import Path
caminho = Path("config.toml")
try:
with caminho.open("rb") as arquivo:
config = tomllib.load(arquivo)
except FileNotFoundError:
raise SystemExit(f"Arquivo não encontrado: {caminho}")
except tomllib.TOMLDecodeError as erro:
raise SystemExit(f"TOML inválido em {caminho}: {erro}")Não use um except Exception genérico para continuar com valores desconhecidos. Em configurações, falhar cedo geralmente é mais seguro do que iniciar parcialmente. Registre o caminho do arquivo e a causa, mas evite expor segredos no log.
Datas e horários em TOML
TOML possui tipos próprios para data, hora e data-hora. O tomllib converte esses valores para classes do módulo datetime:
release_date = 2026-07-23
maintenance = 2026-07-23T22:00:00-03:00data = config["release_date"]
manutencao = config["maintenance"]
print(type(data))
print(type(manutencao))
print(manutencao.tzinfo)Datas com deslocamento recebem informação de fuso. Datas locais, sem deslocamento, não representam um instante global por si só. Ao agendar tarefas ou comparar eventos, defina explicitamente o fuso usado pela aplicação.
Usando Decimal no lugar de float
Por padrão, números decimais TOML viram float. Para valores financeiros, você pode usar o argumento parse_float e converter para Decimal:
import tomllib
from decimal import Decimal
with open("config.toml", "rb") as arquivo:
config = tomllib.load(arquivo, parse_float=Decimal)
print(type(config["database"]["timeout"]))O callable fornecido não pode retornar lista ou dicionário. A conversão é aplicada a cada literal de ponto flutuante encontrado no documento.
tomllib e pyproject.toml
O pyproject.toml centraliza metadados e configurações de muitas ferramentas Python. Você pode ler dados próprios do projeto sem depender do gerenciador que criou o arquivo:
import tomllib
with open("pyproject.toml", "rb") as arquivo:
projeto = tomllib.load(arquivo)
nome = projeto["project"]["name"]
versao = projeto["project"]["version"]
print(f"{nome} {versao}")A estrutura varia conforme o padrão e a ferramenta. Alguns projetos usam a tabela [project]; outros mantêm dados em tabelas específicas. Leia apenas os campos que seu programa realmente controla e trate diferenças de formato. Para entender a etapa de distribuição, veja como publicar um pacote no PyPI.
Organizando configurações por ambiente
Uma estratégia simples é manter valores não secretos em TOML e segredos em variáveis de ambiente. O arquivo pode definir comportamento geral, enquanto senhas e tokens são injetados no deploy. Outra opção é usar tabelas para desenvolvimento, teste e produção:
[environments.development]
debug = true
log_level = "DEBUG"
[environments.production]
debug = false
log_level = "WARNING"ambiente = "production"
opcoes = config["environments"][ambiente]Não armazene credenciais reais em arquivos versionados. Se precisar de valores locais, use um arquivo ignorado pelo Git e forneça um exemplo sem segredos para orientar a equipe.
Testando a leitura da configuração
Como loads trabalha com texto, os testes podem ser rápidos e independentes de arquivos reais:
import tomllib
def test_config_minima():
texto = """
app_name = "teste"
port = 9000
[database]
host = "localhost"
"""
config = tomllib.loads(texto)
validar_config(config)
assert config["port"] == 9000Adicione casos para chaves ausentes, tipos errados, portas inválidas e TOML malformado. Assim, mudanças no esquema de configuração não quebram silenciosamente o sistema.
Boas práticas com tomllib
- Abra arquivos em modo binário ao usar
load. - Use
loadspara strings e testes. - Valide regras do negócio depois da análise sintática.
- Não registre tokens, senhas ou o dicionário completo em logs.
- Defina valores padrão apenas para opções realmente opcionais.
- Limite o tamanho de conteúdo recebido de fontes não confiáveis.
- Documente o esquema esperado com um arquivo de exemplo.
- Mantenha configurações de ferramentas no
pyproject.tomlquando isso simplificar o projeto.
Conclusão
O tomllib no Python oferece uma forma direta e segura de ler TOML usando apenas a biblioteca padrão. Ele converte tabelas, arrays, números, booleanos e datas para tipos Python, gera uma exceção específica para sintaxe inválida e permite personalizar a conversão de valores decimais.
O módulo resolve a etapa de leitura, mas a qualidade da configuração depende de validação, mensagens claras, proteção de segredos e testes. Ao combinar TOML com uma estrutura bem definida, você reduz alterações espalhadas pelo código e facilita a execução do mesmo projeto em diferentes ambientes.







