Ferramentas de Depuração
O Python vem com breakpoint() e pdb, integra-se com REPLs mais ricos como ipdb, suporta depuradores de anexo remoto e depende de logging estruturado para produção. Escolha a ferramenta para reprodução local vs. observação de sistemas ao vivo.
Referência de Ferramentas de Depuração
| Ferramenta | Tipo | Descrição |
|---|---|---|
breakpoint() | ponto de entrada do depurador stdlib | Chama o hook sys.breakpoints() (padrão pdb.set_trace) |
pdb / pdb.pm() | post-mortem | Inspeciona a pilha após exceção |
ipdb | REPL aprimorado | Conclusão de aba IPython e realce de sintaxe |
debugpy | anexo remoto | VS Code/PyCharm anexa ao processo em execução |
logging | sinal de produção | Contexto estruturado sem parar threads |
faulthandler | dump de falha | Rastreamento de dump em SIGABRT/hang |
tracemalloc | memória | Instantâneos de alocação (veja cenários de memória) |
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
def charge(amount: int) -> int:
breakpoint() # Python 3.14: respeita PYTHONBREAKPOINT
if amount < 0:
raise ValueError("negativo")
return amount * 100
# post-mortem em pytest: pytest --pdb
# logging:
import logging
log = logging.getLogger(__name__)
log.exception("falha ao carregar", extra={"amount": amount})Quando usar isso:
- Reproduzir um bug de lógica com variáveis locais intactas
- Inspecionar a pilha após uma exceção em CI
- Anexar a um pod de staging sem editar o código
- Correlacionar relatórios de usuários com logs de requisição em produção
Exemplo de Trabalho
import logging
import sys
from contextlib import contextmanager
# --- configuração de logging estruturado ---
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
log = logging.getLogger("billing")
@contextmanager
def request_context(request_id: str):
old = logging.LoggerAdapter(log, {"request_id": request_id})
try:
yield old
finally:
pass
# --- comandos de sessão pdb (referência de comentário para leitores) ---
# p variável -> imprimir
# n -> próxima linha
# s -> entrar no passo
# w -> onde na pilha
# l -> listar código fonte
# c -> continuar
def apply_discount(total_cents: int, pct: int) -> int:
if pct < 0 or pct > 100:
log.error("pct inválido", extra={"pct": pct})
raise ValueError("pct fora do intervalo")
discounted = total_cents * (100 - pct) // 100
log.info("descontado", extra={"before": total_cents, "after": discounted})
return discounted
def debug_example() -> None:
# breakpoint condicional apenas em dev
if sys.flags.debug_mode: # ou os.getenv("DEBUG_PDB") == "1"
breakpoint()
print(apply_discount(10_00, 10))
# --- helper post-mortem ---
def run_with_pm(fn):
try:
return fn()
except Exception:
import pdb
pdb.post_mortem()
raise
# --- faulthandler para hangs ---
import faulthandler
faulthandler.enable()# pytest com pdb em caso de falha
uv run pytest tests/test_billing.py --pdb -x
# depuração remota (debugpy) - iniciar listener na inicialização do app quando DEBUG_ATTACH=1
# VS Code anexa à porta 5678O que isso demonstra:
loggingregistra valores de negócios sem parar threads de serviçobreakpoint()pausa localmente; proteja com flag de ambiente em caminhos de código compartilhadospytest --pdbentra em modo post-mortem em falhas de asserçãofaulthandlerajuda quando processos travam sem levantar exceções
Mergulho Profundo
Como Funciona
breakpoint()consultaPYTHONBREAKPOINT(padrãopdb.set_trace)- Depuradores rodam no mesmo processo; breakpoints bloqueiam essa thread ou processo
debugpyescuta em uma porta; IDE injeta breakpoints sem reimplantar- Logging deve ser estruturado em produção; pdb é para reprodução em dev/staging
Lista de Comandos pdb
| Comando | Ação |
|---|---|
h | ajuda |
n | próximo |
s | entrar |
r | retornar |
until | executar até uma linha maior que a atual |
pp expr | imprimir formatado |
!stmt | executar instrução Python |
Notas do Python
# desabilitar breakpoints no ponto de entrada de produção
import os
if os.getenv("ENVIRONMENT") == "production":
os.environ["PYTHONBREAKPOINT"] = "0"Armadilhas
- Deixar
breakpoint()no main - paralisa workers de produção. Correção: guarda de ambiente; ruff pode sinalizar instruções de depuração. - Imprimir segredos em pdb - histórico da sessão registra dados sensíveis. Correção: redigir; usar logging com filtros.
- Depuração remota aberta em 0.0.0.0 em produção - risco de RCE. Correção: apenas em staging, túnel SSH, autenticação.
- Depuração com
printem loops intensos - I/O mais lento que o bug. Correção: logging amostrado em INFO/WARN. - Otimização de variáveis sob
-O-asserte alguns caminhos de depuração são removidos. Correção: não confie em assert para validação de produção. pytest --pdbem xdist paralelo - workers anexam de forma confusa. Correção:-n0ao depurar.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
ipdb | querer recursos do IPython | imagens mínimas de CI sem dependência |
pudb | TUI de tela cheia | servidores headless |
rastreamentos de sentry | agregação de erros em produção | depuração de locais |
rastreamentos de OpenTelemetry | latência entre serviços | bugs de lógica linha a linha |
FAQs
Qual é a diferença entre pdb e ipdb?
pdb é stdlib. ipdb o envolve com conclusão do IPython e tracebacks melhores. Instale ipdb apenas no grupo de dependências de dev.
Como uso breakpoint() no FastAPI?
Defina PYTHONBREAKPOINT=ipdb.set_trace em dev. Um worker (uvicorn --reload) evita confusão multi-processo. Nunca em imagens de produção.
Quando devo usar logging em vez de pdb?
Produção, staging sob carga e qualquer defeito que você não consiga reproduzir localmente. Logs preservam evidências após o processo continuar.
Como funciona o pytest --pdb?
Na falha do teste, pytest abre o modo post-mortem no frame da exceção. Combine com -x para parar na primeira falha.
Posso depurar código asyncio?
Sim com breakpoint() em corrotinas quando o loop está rodando sob um único worker. Para casos complexos use o modo de depuração asyncio (PYTHONASYNCIODEBUG=1).
Como anexo o VS Code com debugpy?
Adicione um debugpy.listen(("127.0.0.1", 5678)) protegido e debugpy.wait_for_client() apenas em staging; encaminhe a porta via SSH.
O que é PYTHONBREAKPOINT=0?
Desabilita chamadas breakpoint() - útil em pontos de entrada de produção para evitar que commits acidentais parem deploys.
Devo usar print em bibliotecas?
Não. Bibliotecas registram via logging.getLogger(__name__). Aplicações configuram handlers e níveis.
Como faço logging em JSON?
Use python-json-logger ou structlog em aplicações; inclua request_id, hash do ID do usuário e tipo de erro - não senhas brutas.
O Django 5.2 muda a depuração?
django-debug-toolbar continua sendo apenas para dev. Use a configuração de logging do Django; nunca exponha a barra de ferramentas em configurações de produção.
Como depuro tarefas Celery?
celery worker --loglevel=INFO mais IDs de tarefa nos logs. Reproduza eager com task.apply() no shell antes do anexo remoto.
Quando faulthandler é suficiente?
Quando processos travam sem exceções - deadlock ou stall de extensão C. SIGUSR1 pode acionar dump de pilha se configurado.
Relacionados
- Bugs de Argumentos Padrão Mutáveis - inspecionar com pdb
- Deadlocks e Bloqueio do Loop em asyncio - modo de depuração asyncio
- Cenários de Vazamento de Memória - companheiro tracemalloc
- Conflitos de Dependência e Ambiente - verificar interpretador em pdb
- Snippets de Refatoração de Depuração - correções após a causa raiz encontrada
Versões da Stack: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 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+.