Melhores Práticas de Erros e Logging
Regras operacionais para exceções e logs em serviços Python de produção.
Como Usar Esta Lista
- Aplique primeiro nas fronteiras do serviço - manipuladores HTTP, pontos de entrada de CLI, workers.
- Emparelhe cada regra com CI (
pytest,-W error, testes de formato de log). - Revise os logs de plantão trimestralmente - se uma regra não ajudou em incidentes, reforce-a.
A - Exceções
- Capture tipos de exceção específicos. Nunca use
except:genérico em código de aplicação. - Encadeie com
raise DomainError() from excnas fronteiras. Preserve a causa raiz em logs e Sentry. - Use uma hierarquia customizada rasa por contexto delimitado. Manipuladores capturam
BillingError, nãoException. - Falhe rapidamente em erros de programador. Deixe
AssertionErroreTypeErrorsubirem em desenvolvimento; corrija o código. - Manipule
ExceptionGroupcomexcept*em códigoTaskGroupassíncrono. Não assuma falha única.
B - Configuração de Logging
- Configure o logging uma vez na entrada da aplicação. Bibliotecas apenas
getLogger(__name__). - Use formatação
%preguiçosa:log.info("id=%s", id). Evite f-strings em chamadas de log. - Defina o nível a partir do ambiente. DEBUG localmente, INFO/WARNING em produção.
- Anexe um arquivo rotativo ou envie para um agregador. stderr sozinho é perdido na reinicialização do contêiner.
- Silencie ruído de terceiros de forma restrita.
urllib3,asyncio- filtre por módulo, documente o porquê.
C - Operações Estruturadas
- Emita JSON ou key=value em produção. Pesquise
request_id,user_id,duration_ms. - Vincule IDs de correlação em middleware.
contextvarspara campos de escopo de requisição. - Registre exceções com
log.exceptiondentro deexcept. Uma stack trace por incidente, não impressões duplicadas. - Mensagem de evento estática, campos dinâmicos.
"payment_failed"+order_id=, não frases interpoladas. - Redacione segredos e PII em processadores. Tokens e e-mails nunca em campos de log em texto puro.
D - Retentativas e Avisos
- Retente apenas falhas transitórias e idempotentes. Limite tentativas; backoff exponencial com jitter.
- Levante erro encadeado quando as retentativas se esgotarem. Inclua a contagem de tentativas na mensagem.
- Deprecie com
DeprecationWarninge versão de remoção. Execute CI com avisos como erros para seu código. - Use
stacklevel=2+em wrappers de aviso. Culpe a linha do chamador no traceback. - Nunca use avisos para ramificação de negócios. Avisos notificam; exceções controlam o fluxo.
E - Política e Revisão
- Não engula silenciosamente - registre ou re-levante.
suppressapenas para caminhos verdadeiramente opcionais. - Mapeie exceções de domínio para códigos HTTP/status em uma camada. Não espalhadas em repositórios.
- Teste tipos de exceção e emissões de aviso.
pytest.raises,deprecated_call. - Documente o runbook de plantão: qual consulta de log significa o quê. Link do alerta para o dashboard.
- Revise as taxas de erro após os lançamentos. Novos tipos de exceção devem ser esperados e documentados.
FAQs
Qual é o pior hábito único?
except: pass genérico - esconde a corrupção de dados até que a reconciliação falhe semanas depois.
Devo registrar e levantar?
Sim, nas fronteiras, quando os operadores precisam de visibilidade e os chamadores precisam de falha - não em cada loop interno.
Como eu imponho isso em CI?
ruff E722, pytest com filterwarnings=error, e testes de integração que afirmam o esquema JSON do log.
print vs logging?
print para notebooks e scripts únicos; logging para qualquer coisa implantada.
Quão verboso deve ser o INFO?
Uma linha por fronteira de requisição bem-sucedida; DEBUG para internos. INFO por linha de alta cardinalidade inunda os agregadores.
Preciso de Sentry se tiver logs?
Complementares - Sentry agrupa stack traces; logs fornecem contexto cronológico. Conecte ambos com a mesma tag de release.
Como lidar com exceções de terceiros?
Envolva uma vez na fronteira do adaptador em um erro de domínio; registre o original com from exc.
Bibliotecas devem registrar erros?
Bibliotecas registram contexto em WARNING/ERROR; a aplicação decide os manipuladores e a mensagem final do usuário.
E quanto ao logging em asyncio?
Use manipuladores amigáveis a async ou enfileire para thread; evite I/O bloqueante na thread do event loop.
Como migro de depuração com print?
Substitua por log.debug e execute localmente em DEBUG; remova antes de mesclar ou controle por flag.
Relacionados
- Noções Básicas de Exceções - introdução a try/except
- Logging Estruturado e Contextual - detalhes de JSON
- Retentativas e Backoff - políticas de retentativa
- Avisos e Depreciações - remoções suaves
Versões de Stack: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.