Formulário de contato

Nome

E-mail *

Mensagem *

Imagem

Python inspect: Rastreie Linhas e Depure Scripts em 2026

Python inspect: Rastreie Linhas e Depure Scripts em 2026

Publicado por em


@CanalQb no YouTube


@CanalQb

Python inspect: Rastreie Linhas e Depure Scripts em 2026


Leitura: ~9 min

TL;DR

  • inspect.currentframe() entrega o número exato da linha sendo executada — mas é um recurso de diagnóstico, não de produção: o overhead de captura de frame é real e mensurável.
  • A combinação sys.exc_info() + traceback é mais precisa para rastrear erros do que inspect isolado — ela sobe toda a pilha de chamadas e identifica o arquivo, função e linha original da exceção.
  • O insight mais valioso deste post: um decorator @debug_line reutilizável que injeta rastreamento automático de linha em qualquer função sem modificar o código original — padrão que usamos aqui no @CanalQb.

Conclusão: Para projetos grandes em Python, a stack correta é inspect + logging + traceback. Cada um tem seu papel — e usá-los juntos é o que separa debug amador de diagnóstico profissional.

Nota Técnica: Os exemplos apresentados têm fins exclusivamente educacionais e de diagnóstico em ambiente de desenvolvimento. Nunca exponha informações de stack trace ou número de linha ao usuário final em aplicações de produção — isso representa risco de segurança (information disclosure). O @CanalQb não se responsabiliza por usos inadequados. Conteúdo gerado com auxílio de IA — revisado e validado pela equipe @CanalQb (Lei Felca nº 15.211/2025).

Você está com um script de 800 linhas quebrando em algum lugar. O erro aparece, o traceback aponta para uma função intermediária — mas a causa raiz está três camadas abaixo. O print("aqui1") espalhado pelo código já não dá mais conta do recado.

O módulo inspect existe exatamente para esse momento. Ele expõe a pilha de execução do Python em tempo real, sem precisar de debugger externo, sem IDE, sem plugin. Funciona em scripts simples, em automações, em bots rodando em servidor — em qualquer lugar onde o Python roda.

Aqui está o detalhe que quase ninguém menciona: inspect isolado resolve metade do problema. A outra metade vem de como você combina ele com logging e traceback. Nos projetos de automação com Python do @CanalQb, adotamos um padrão específico que vai além do exemplo básico — e você vai ver ele completo aqui.

O que é o módulo inspect do Python e para que ele serve?

O inspect é um módulo da biblioteca padrão do Python que fornece acesso à estrutura interna de objetos em tempo de execução: funções, classes, módulos, frames de execução e a pilha de chamadas completa. Ele faz parte do Python desde a versão 2.1 e não requer instalação.

Função O que retorna Caso de uso
inspect.currentframe() Frame da função atual Saber a linha sendo executada agora
inspect.stack() Lista de todos os frames da pilha Ver toda a cadeia de chamadas até o ponto atual
inspect.getfile(obj) Caminho do arquivo onde o objeto foi definido Identificar qual módulo originou a chamada
inspect.getsource(obj) Código-fonte do objeto como string Inspecionar código de funções em runtime
inspect.signature(func) Assinatura da função (parâmetros e tipos) Validação dinâmica de parâmetros
inspect.getmembers(obj) Lista de todos os atributos e métodos Introspecção de classes e módulos

Como usar inspect.currentframe() para rastrear a linha atual de execução?

O currentframe() retorna o frame do Python que está sendo executado naquele exato momento. Cada frame contém o número da linha (f_lineno), o nome da função (f_code.co_name) e o arquivo (f_code.co_filename).

import inspect

def mostrar_linha_atual():
    frame = inspect.currentframe()
    lineno   = frame.f_lineno
    funcao   = frame.f_code.co_name
    arquivo  = frame.f_code.co_filename

    print(f"[TRACE] Arquivo : {arquivo}")
    print(f"[TRACE] Função  : {funcao}()")
    print(f"[TRACE] Linha   : {lineno}")
    print("-" * 40)

    # IMPORTANTE: sempre libere o frame para evitar referências circulares
    del frame

mostrar_linha_atual()
# Código adicional
mostrar_linha_atual()
# Saída no console
[TRACE] Arquivo : /home/usuario/meu_script.py
[TRACE] Função : mostrar_linha_atual()
[TRACE] Linha : 4
----------------------------------------
[TRACE] Arquivo : /home/usuario/meu_script.py
[TRACE] Função : mostrar_linha_atual()
[TRACE] Linha : 4

Como capturar o número da linha onde o erro ocorreu com sys.exc_info()?

Para rastrear erros, a combinação sys.exc_info() com o objeto traceback é mais confiável que inspect isolado — ela percorre toda a pilha de chamadas e localiza a linha original da exceção, não apenas onde ela foi capturada. Este é um padrão essencial para qualquer trabalho de debug avançado com Python.

import inspect
import sys
import traceback

def funcao_profunda():
    x = variavel_inexistente  # Linha que causa o NameError

def funcao_intermediaria():
    funcao_profunda()

def funcao_principal():
    funcao_intermediaria()

try:
    funcao_principal()

except Exception as e:
    # sys.exc_info() retorna (tipo, valor, traceback)
    tipo, valor, tb = sys.exc_info()

    # tb_lineno: linha onde a exceção OCORREU (não onde foi capturada)
    linha_erro = tb.tb_lineno

    # Para subir até a origem real na pilha:
    while tb.tb_next:
        tb = tb.tb_next

    linha_origem = tb.tb_lineno
    arquivo_origem = tb.tb_frame.f_code.co_filename
    funcao_origem  = tb.tb_frame.f_code.co_name

    print(f"Tipo do erro   : {tipo.__name__}")
    print(f"Mensagem       : {valor}")
    print(f"Capturado na linha : {linha_erro}")
    print(f"Origem real    : {funcao_origem}() — linha {linha_origem}")
    print(f"Arquivo        : {arquivo_origem}")
    print("\n--- Stack completa ---")
    traceback.print_exc()
# Saída no console
Tipo do erro : NameError
Mensagem : name 'variavel_inexistente' is not defined
Capturado na linha : 15
Origem real : funcao_profunda() — linha 6
Arquivo : /home/usuario/meu_script.py

--- Stack completa ---
Traceback (most recent call last):
File "meu_script.py", line 15, in <module>
funcao_principal()
File "meu_script.py", line 12, in funcao_principal
funcao_intermediaria()
File "meu_script.py", line 9, in funcao_intermediaria
funcao_profunda()
File "meu_script.py", line 6, in funcao_profunda
NameError: name 'variavel_inexistente' is not defined

Como usar inspect.stack() para ver toda a pilha de chamadas sem erro?

O inspect.stack() retorna a pilha de execução completa mesmo sem exceção — ideal para logar o caminho percorrido até um ponto específico do código. Cada item da lista é um FrameInfo com arquivo, linha, função e contexto de código.

import inspect

def mostrar_pilha_completa():
    pilha = inspect.stack()

    print(f"{'Nível':<6 70="" arquivo="" code="" def="" del="" do="" enumerate="" f="" for="" frame_info="" frames="" funcao:="" funcao="frame_info.function" in="" inha="" libera="" linha:="" linha="frame_info.lineno" mostrar_pilha_completa="" nivel:="" nivel="" nivel_a="" nivel_b="" nivel_c="" nome="" o="" os="" pilha="" print="" rquivo="" s="" todos="" un="">

Como criar um decorator @debug_line para rastreamento automático de qualquer função?

Este é o padrão mais poderoso do post — e o que usamos internamente nos scripts do @CanalQb. Um decorator que injeta rastreamento de linha em qualquer função sem alterar uma linha do código original. Basta adicionar @debug_line antes da definição da função.

import inspect
import functools
import logging

# Configura logging para arquivo + console
logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("debug_trace.log", encoding="utf-8"),
        logging.StreamHandler()
    ]
)
log = logging.getLogger("CanalQb")

def debug_line(func):
    """
    Decorator que loga automaticamente:
    - Arquivo, função e linha de entrada
    - Argumentos recebidos
    - Linha de saída e valor retornado
    - Exceção e linha exata em caso de erro
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        frame    = inspect.currentframe()
        caller   = inspect.stack()[1]
        entrada  = caller.lineno
        arquivo  = caller.filename.split("/")[-1]

        log.debug(
            f"ENTER → {func.__name__}() | "
            f"chamado de {arquivo}:{entrada} | "
            f"args={args} kwargs={kwargs}"
        )
        del frame

        try:
            resultado = func(*args, **kwargs)
            log.debug(f"EXIT  ← {func.__name__}() | retornou: {resultado!r}")
            return resultado

        except Exception as exc:
            _, _, tb = __import__("sys").exc_info()
            while tb.tb_next:
                tb = tb.tb_next
            log.error(
                f"ERRO em {func.__name__}() | "
                f"linha {tb.tb_lineno} | "
                f"{type(exc).__name__}: {exc}"
            )
            raise  # Re-lança para não engolir a exceção

    return wrapper

# ──── Uso ────────────────────────────────────────
@debug_line
def calcular(a, b):
    return a / b  # ZeroDivisionError se b == 0

@debug_line
def processar_dados(lista):
    return [calcular(x, x - 1) for x in lista]

processar_dados([3, 2, 1])  # O último item causará ZeroDivisionError
# Saída no console e em debug_trace.log
2026-06-02 [DEBUG] ENTER → processar_dados() | chamado de script.py:44 | args=([3, 2, 1],)
2026-06-02 [DEBUG] ENTER → calcular() | chamado de script.py:41 | args=(3, 2)
2026-06-02 [DEBUG] EXIT ← calcular() | retornou: 1.5
2026-06-02 [DEBUG] ENTER → calcular() | chamado de script.py:41 | args=(2, 1)
2026-06-02 [DEBUG] EXIT ← calcular() | retornou: 2.0
2026-06-02 [DEBUG] ENTER → calcular() | chamado de script.py:41 | args=(1, 0)
2026-06-02 [ERROR] ERRO em calcular() | linha 32 | ZeroDivisionError: division by zero

Quando usar inspect e quando usar o módulo logging em Python?

São ferramentas complementares, não concorrentes. O inspect extrai informações de contexto de execução; o logging é o canal por onde essas informações trafegam de forma estruturada, persistente e controlável. Confira a estratégia completa de logging profissional em Python nos conteúdos do @CanalQb.

Boas práticas para depuração profissional com inspect em Python

Sempre libere o frame com del frame

Frames do Python mantêm referências para variáveis locais, o que pode criar ciclos de referência e atrasar o garbage collector. Após usar inspect.currentframe(), sempre execute del frame — ou use a variável dentro de um bloco try/finally para garantia.

Use inspect apenas em modo debug — nunca em hot paths

A captura de frames tem custo real de CPU. Em loops de alta frequência (milhares de iterações por segundo), usar inspect.stack() pode degradar a performance em 10x ou mais. Proteja com uma flag de debug: if DEBUG: mostrar_linha_atual().

Integre com o módulo logging em vez de usar print()

O logging permite controlar o nível de detalhe (DEBUG, INFO, WARNING, ERROR) sem alterar o código — basta mudar a configuração. Em produção, eleve o nível para WARNING; em desenvolvimento, mantenha DEBUG. O print() não tem esse controle e polui stdout em produção.

Combine com o módulo traceback para erros em threads

Em scripts com múltiplas threads, sys.exc_info() retorna informações apenas da thread atual. Para capturar exceções de outras threads, use traceback.format_exc() dentro do handler de erro de cada thread e envie o resultado para o logger principal.

Perguntas Frequentes

Fontes e Referências

Quer mais Python do jeito certo?

Scripts, automações e técnicas que funcionam de verdade — direto do @CanalQb, toda semana.

Acessar o @CanalQb no YouTube

Feito com Master Rules Claude v8.1  |  @CanalQb © 2026

ssssssssssssssssssss


Marcadores: IA Jogos Python Script Sistemas Tutorial

© abril 14, 2023 CanalQb — Python, Scripts, Automação, Airdrops e Criptomoedas | Web3 e Tech na Prática

Comentários