Imprimir pilha de chamadas atual de um método no código Python


Respostas:


319

Aqui está um exemplo de como obter a pilha através do módulo traceback e imprimi-la:

import traceback

def f():
    g()

def g():
    for line in traceback.format_stack():
        print(line.strip())

f()

# Prints:
# File "so-stack.py", line 10, in <module>
#     f()
# File "so-stack.py", line 4, in f
#     g()
# File "so-stack.py", line 7, in g
#     for line in traceback.format_stack():

Se você realmente deseja apenas imprimir a pilha no stderr, pode usar:

traceback.print_stack()

Ou para imprimir em stdout (útil se desejar manter a saída redirecionada em conjunto), use:

traceback.print_stack(file=sys.stdout)

Mas obtê-lo via traceback.format_stack()permite fazer o que quiser com ele.


Como fazer o mesmo para todos os outros threads (estou falando de threads que não controlo)  ?
user2284570

Talvez eu esteja perdendo alguma coisa aqui, mas você chama f que é o único objetivo aqui é chamar g e não faz mais nada. Por que
Chris

6
@ Chris: É apenas um exemplo. Possui várias funções para deixar claro que format_stack () imprime todas as chamadas na pilha.
RichieHindle

Se você deseja obter uma saída mais detalhada (incluindo vars etc.), consulte esta questão relacionada e esta .
Albert

@ user2284570: Você pode usar sys._current_frames(). Por exemplo, py_better_exchookdump_all_thread_tracebacks faz isso (aviso: eu escrevi isso).
Albert

93
import traceback
traceback.print_stack()

8
Na verdade, eu gosto do traceback.print_exc()que lhe dá quase a mesma coisa que você obteria sem a exceptdeclaração (e também é menos codificadora do que a resposta aceita).
22680 martineau

34
traceback.print_exc()imprime o rastreamento de pilha para qualquer exceção que você possa estar manipulando - mas isso não resolve a questão original, que é como imprimir a pilha atual ("onde você está agora", em vez de "onde estava o seu código quando a última exceção ocorreu" off, se houver ".)
Tom Swirly


17

Se você usar o depurador python, não apenas investigará interativamente as variáveis, mas poderá obter a pilha de chamadas com o comando "where" ou "w".

Então, no topo do seu programa

import pdb

Em seguida, no código em que você deseja ver o que está acontecendo

pdb.set_trace()

e você cai em um prompt


2
Venho programando em Python há mais de uma década. Há assim que muitas vezes eu poderia ter usado isso! Não acredito que estou descobrindo agora.
precisa saber é o seguinte

1
Como isso se relaciona where?
Skia.heliou

4
Para responder à parte "where" da pergunta: Depois de receber o prompt pdb, (pdb) digite wheree ele imprimirá o rastreamento da pilha no terminal.
quer

1
O Python 3.7 e superior têm uma função interna breakpoint()que evita a necessidade de importar o pdb.
user650654

6

para quem precisa imprimir a pilha de chamadas enquanto usa o pdb, basta

(Pdb) where

2

Aqui está uma variação da excelente resposta do @ RichieHindle, que implementa um decorador que pode ser aplicado seletivamente às funções conforme desejado. Funciona com o Python 2.7.14 e 3.6.4.

from __future__ import print_function
import functools
import traceback
import sys

INDENT = 4*' '

def stacktrace(func):
    @functools.wraps(func)
    def wrapped(*args, **kwds):
        # Get all but last line returned by traceback.format_stack()
        # which is the line below.
        callstack = '\n'.join([INDENT+line.strip() for line in traceback.format_stack()][:-1])
        print('{}() called:'.format(func.__name__))
        print(callstack)
        return func(*args, **kwds)

    return wrapped

@stacktrace
def test_func():
    return 42

print(test_func())

Saída da amostra:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42

Escrevi minha própria versão do decorador antes de ver isso. Votado.
Sida Zhou

0

Instale o Inspecione

pip3 install inspect-it --user

Código

import inspect;print(*['\n\x1b[0;36;1m| \x1b[0;32;1m{:25}\x1b[0;36;1m| \x1b[0;35;1m{}'.format(str(x.function), x.filename+'\x1b[0;31;1m:'+str(x.lineno)+'\x1b[0m') for x in inspect.stack()])

você pode criar um trecho dessa linha

mostrará uma lista da pilha de chamadas de função com um nome de arquivo e um número de linha

lista do início até onde você coloca esta linha

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.