Encontrar e corrigir bugs é uma das habilidades mais importantes que um desenvolvedor Python pode dominar. Estima-se que desenvolvedores gastam entre 30% e 50% do seu tempo depurando código — e fazer isso de forma eficiente pode literalmente dobrar sua produtividade. Neste guia completo, você vai aprender desde o básico do pdb (Python Debugger) até técnicas avançadas de depuração usadas por engenheiros seniores.

Se você ainda usa print() para tudo, prepare-se para descobrir um mundo de ferramentas que vão transformar sua forma de programar. Vamos abordar o depurador interativo pdb, a função breakpoint() introduzida no Python 3.7, debuggers visuais do VS Code e PyCharm, e técnicas profissionais como pós-mortem e depuração remota.

O Que é Depuração de Código?

Depuração (ou debugging) é o processo sistemático de identificar, isolar e corrigir defeitos no código fonte. Diferente de testar — que verifica se o código funciona — a depuração investiga por que ele não funciona. É um trabalho de detetive: você coleta pistas, formula hipóteses e testa cada uma até encontrar a causa raiz do problema.

O Python oferece um ecossistema maduro de ferramentas de depuração, desde o built-in pdb até IDEs completos com interfaces gráficas. A chave é saber qual ferramenta usar em cada situação e, mais importante, como pensar durante o processo de depuração.

Por Que Não Usar Apenas print()?

O print() é a ferramenta mais básica e todo mundo começa por ela. Mas ela tem limitações severas:

  • Você precisa modificar o código, adicionar prints, rodar de novo, remover os prints — um ciclo lento e repetitivo
  • Não consegue inspecionar variáveis em tempo real durante a execução
  • Não permite pausar a execução, avançar passo a passo ou alterar variáveis
  • Pode alterar o comportamento do programa (efeitos colaterais em produção)
  • Em loops grandes, prints podem gerar milhões de linhas de saída inútil

O pdb resolve todos esses problemas: você inspeciona variáveis sem modificar o código, controla a execução passo a passo, define breakpoints condicionais e até executa código Python arbitrário durante a pausa.

Introdução ao pdb — Python Debugger

O pdb (Python Debugger) é o depurador interativo built-in do Python. Ele faz parte da biblioteca padrão desde o Python 1.5 — ou seja, você não precisa instalar nada. Com ele, você pode pausar a execução do programa em qualquer ponto, inspecionar o valor de variáveis, executar código linha a linha e entender exatamente o que está acontecendo.

Iniciando o pdb

Existem três maneiras principais de iniciar uma sessão de depuração com pdb:

# 1. Importando e usando explicitamente
import pdb; pdb.set_trace()

2. Usando breakpoint() (Python 3.7+)

breakpoint()

3. Executando um script com pdb

python -m pdb meu_script.py

A função breakpoint() é a forma moderna e recomendada. Por padrão, ela chama pdb.set_trace(), mas você pode redirecioná-la para outros debuggers configurando a variável de ambiente PYTHONBREAKPOINT. Isso significa que você pode deployar código com breakpoints e ativá-los seletivamente em diferentes ambientes.

Comandos Essenciais do pdb

Quando a execução pausa em um breakpoint, você entra no shell interativo do pdb. Aqui estão os comandos que você mais vai usar:

ComandoAbreviaçãoO que faz
listlMostra o código ao redor da linha atual
nextnExecuta a próxima linha (sem entrar em funções)
stepsExecuta a próxima linha (entrando em funções chamadas)
continuecContinua a execução até o próximo breakpoint
printpImprime o valor de uma expressão
ppImprime com formatação bonita (pretty-print)
argsaMostra todos os argumentos da função atual
wherewMostra a pilha de chamadas (stack trace)
upuSobe um nível na pilha de chamadas
downdDesce um nível na pilha de chamadas
breakbDefine um breakpoint em uma linha ou função
clearclRemove um breakpoint
quitqSai do depurador e encerra o programa

Exemplo Prático com pdb

Vamos ver o pdb em ação com um exemplo real:

def calcular_media(notas):
    total = sum(notas)
    media = total / len(notas)
    return media

def processar_alunos(alunos): resultados = [] for aluno in alunos: breakpoint() # Pausa aqui para inspecionar cada aluno media = calcular_media(aluno['notas']) aluno['media'] = media resultados.append(aluno) return resultados

alunos = [ {'nome': 'Ana', 'notas': [8.5, 9.0, 7.5]}, {'nome': 'Carlos', 'notas': [6.0, 7.0]}, {'nome': 'Beatriz', 'notas': []}, # Bug! Divisão por zero ]

print(processar_alunos(alunos))

Ao executar, o pdb pausa na primeira iteração. Você pode digitar p aluno para ver os dados, n para avançar, c para continuar até o próximo breakpoint. Quando chegar no terceiro aluno com lista vazia, o erro fica óbvio antes mesmo de acontecer.

breakpoint() — A Forma Moderna de Depurar

Introduzida no PEP 553, a função breakpoint() é a maneira recomendada de inserir pontos de parada no código desde o Python 3.7. Sua grande vantagem é a flexibilidade: você pode controlar para qual debugger ela direciona sem alterar o código fonte.

Configure o debugger padrão com a variável de ambiente PYTHONBREAKPOINT:

# Usar pdb padrão (já é o default)
set PYTHONBREAKPOINT=pdb.set_trace

Usar ipdb (mais bonito, com syntax highlight)

set PYTHONBREAKPOINT=ipdb.set_trace

Desativar todos os breakpoints (útil em produção)

set PYTHONBREAKPOINT=0

Isso é revolucionário para times de desenvolvimento: você pode comitar código com breakpoint() e a equipe decide localmente se quer ativar ou ignorar esses pontos. Em produção, basta definir PYTHONBREAKPOINT=0 e todos os breakpoints são ignorados silenciosamente.

Depuração Pós-Mortem com pdb

Uma das técnicas mais poderosas é a depuração pós-mortem. Quando uma exceção não tratada ocorre, o pdb pode automaticamente abrir uma sessão interativa no local exato do erro, permitindo inspecionar todas as variáveis no momento da falha.

import pdb

try: resultado = 10 / 0 except ZeroDivisionError: pdb.post_mortem() # Abre depuração no ponto da exceção

Você também pode executar qualquer script em modo pós-mortem com:

python -m pdb -c continue meu_script.py

Quando uma exceção ocorrer, o pdb entra automaticamente em modo pós-mortem. Você pode então usar comandos como where para ver a pilha completa, p variavel para inspecionar valores, e up/down para navegar entre os frames da pilha.

Debuggers de Terceiros que Você Precisa Conhecer

O pdb é poderoso, mas existem alternativas que oferecem recursos extras:

ipdb — pdb com Interface Melhorada

O ipdb é o pdb com a engine do IPython. Ele oferece syntax highlighting, autocomplete, histórico de comandos e integração com o ecossistema IPython/Jupyter. Instale com pip install ipdb e use da mesma forma que o pdb.

IPython — %debug Magia

Se você usa Jupyter Notebook ou IPython, o comando mágico %debug ativa o depurador pós-mortem automático após qualquer exceção. Basta executar %debug depois de um erro e você cai diretamente no frame onde a exceção ocorreu.

PyCharm Debugger

O PyCharm possui um dos debuggers visuais mais completos do mercado. Você pode definir breakpoints clicando na margem, inspecionar variáveis em uma interface gráfica, avaliar expressões arbitrárias e até modificar variáveis durante a execução. O modo "Evaluate Expression" (Alt+F8) permite executar qualquer código Python no contexto atual.

VS Code Python Debugger

O VS Code oferece uma experiência de depuração excelente com a extensão Python da Microsoft. Recursos como inline values (valores das variáveis aparecem ao lado do código), debug console interativo, conditional breakpoints e logpoints (breakpoints que só logam, sem pausar) fazem dele uma ferramenta extremamente produtiva.

Logging Estratégico — Quando o Debugger Não é Suficiente

Em produção, você não pode usar um debugger interativo. É aí que entra o módulo logging do Python. Um sistema de logging bem configurado é essencial para depurar problemas em ambientes de produção.

import logging

logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', filename='app.log' )

logger = logging.getLogger(name) logger.debug('Processando pedido do usuário %s', user_id) logger.info('Pedido %s processado com sucesso', order_id) logger.warning('Tempo de resposta acima do limite: %.2fs', elapsed) logger.error('Falha ao processar pagamento: %s', str(error))

O logging bem estruturado permite que você investigue problemas sem precisar reproduzi-los localmente. Combine logging com ferramentas de observabilidade como Sentry, Datadog ou New Relic para ter visibilidade total do comportamento da sua aplicação.

Técnicas Avançadas de Depuração

Breakpoints Condicionais

No pdb, você pode definir breakpoints que só disparam quando uma condição é verdadeira:

# No shell do pdb:
b 42, x > 100
# Só para na linha 42 quando x for maior que 100

Com breakpoint() + condicional:

breakpoint() # E usa 'condition' no shell do pdb

Depuração Remota

Com ferramentas como remote-pdb ou pdb-over-http, você pode depurar código rodando em servidores remotos ou containers Docker. Isso é especialmente útil para microserviços e aplicações em cloud.

IceCream — Print Debugging Inteligente

A biblioteca icecream transforma o print debugging em algo muito mais produtivo. Em vez de print(f"x = {x}"), você usa ic(x) e ela automaticamente mostra o nome da variável, o valor, o arquivo e a linha — sem nenhum esforço extra.

from icecream import ic

def calcular(x, y): resultado = x * y + 10 ic(x, y, resultado) # ic| x: 5, y: 3, resultado: 25 return resultado

Análise de Tracebacks

Entender tracebacks é uma habilidade essencial. O módulo traceback permite formatar e extrair informações detalhadas de exceções. Em aplicações web, use middlewares que capturam tracebacks completos e os enviam para sistemas de monitoramento.

Erros Comuns e Como Depurá-los

AttributeError: 'NoneType' object has no attribute 'X'

Esse é um dos erros mais frequentes em Python. A causa quase sempre é uma função que retorna None quando você esperava outro valor. Use pdb para inspecionar o retorno da função antes de acessar atributos.

breakpoint()  # Inspecione o retorno antes do acesso
usuario = buscar_usuario(id)
print(usuario.nome)  # Se usuario for None, erro aqui

IndexError e KeyError

Erros de índice em listas ou chaves em dicionários geralmente indicam suposições incorretas sobre os dados. Um breakpoint antes do acesso revela rapidamente o problema.

NameError inesperado

Muitas vezes causado por variáveis definidas em escopo condicional que não foi executado. Um pdb.set_trace() no local suspeito mostra quais variáveis estão realmente definidas.

Estratégia de Depuração em 5 Passos

Depois de anos depurando código, desenvolvi este fluxo que funciona para a maioria dos casos:

  1. Reproduza o bug — Antes de qualquer coisa, tenha uma maneira confiável de reproduzir o problema. Sem isso, você está depurando no escuro.
  2. Isole a causa — Use breakpoints estratégicos para encontrar exatamente onde o comportamento desvia do esperado. Comece pelo meio do fluxo e vá estreitando.
  3. Entenda o porquê — Não corrija apenas o sintoma. Inspecione as variáveis, entenda qual suposição do seu código estava errada.
  4. Corrija e teste — Faça a correção mínima necessária e verifique se o bug foi resolvido sem introduzir novos problemas.
  5. Documente — Escreva um teste para o bug que você encontrou. Isso previne regressões e ajuda outros desenvolvedores.

Lembre-se: a depuração não é sobre achar o erro — é sobre entender o que o código realmente está fazendo. Quando você entende o comportamento real versus o esperado, a solução se torna óbvia.

Quer se aprofundar ainda mais em Python? Veja nosso guia completo sobre Python Clean Code e Boas Práticas para escrever código que é mais fácil de depurar desde o início. E para testes automatizados que previnem bugs antes que eles apareçam, confira nosso tutorial de Testes Automatizados com Pytest.

Conclusão

Dominar a depuração em Python é um investimento que se paga múltiplas vezes ao longo da sua carreira. O pdb e a função breakpoint() são ferramentas essenciais que todo desenvolvedor Python deveria conhecer. Combinados com debuggers visuais, logging estratégico e técnicas como pós-mortem, você terá um arsenal completo para encontrar e corrigir bugs com rapidez e confiança.

A chave é praticar: comece substituindo seus prints por breakpoints, aprenda um comando novo do pdb por dia, e em uma semana você já estará depurando como um profissional. O tempo investido em aprender a depurar bem é o tempo que você vai economizar em cada bug que encontrar pelo resto da sua carreira.