Stampa lo stack di chiamate corrente da un metodo nel codice Python


Risposte:


319

Ecco un esempio di come ottenere lo stack tramite il modulo traceback e stamparlo:

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 vuoi davvero solo stampare la pila su stderr, puoi usare:

traceback.print_stack()

Oppure per stampare su stdout (utile se si desidera mantenere insieme l'output reindirizzato), utilizzare:

traceback.print_stack(file=sys.stdout)

Ma ottenerlo tramite traceback.format_stack()ti consente di fare quello che ti piace.


Come fare lo stesso per tutti gli altri thread (sto parlando di thread che non controllo)  ?
user2284570,

Forse mi manca qualcosa qui, ma tu chiami f il cui unico scopo è qui è chiamare g e non fa nient'altro. Perché
Chris,

6
@ Chris: è solo un esempio. Ha più funzioni per chiarire che format_stack () stampa tutte le chiamate nello stack.
RichieHindle,

Se si desidera ottenere un output più dettagliato (compresi var, ecc.), Vedere questa domanda correlata e questa .
Albert,

@ user2284570: è possibile utilizzare sys._current_frames(). Ad esempio py_better_exchook lodump_all_thread_tracebacks fa (disclaimer: l'ho scritto).
Albert,

93
import traceback
traceback.print_stack()

8
In realtà, mi piace traceback.print_exc()che ti dà quasi la stessa cosa che avresti ottenuto senza la exceptdichiarazione (ed è anche meno codificante della risposta accettata).
martineau,

34
traceback.print_exc()stampa la traccia dello stack per qualsiasi eccezione che potresti gestire - ma questo non risolve la domanda originale, che è come stampare lo stack corrente ("dove sei ora" invece di "dove si trovava il tuo codice quando è passata l'ultima eccezione spento, se presente ".)
Tom Swirly,


17

Se si utilizza il debugger di Python, non solo il sondaggio interattivo delle variabili, ma è possibile ottenere lo stack di chiamate con il comando "where" o "w".

Quindi nella parte superiore del tuo programma

import pdb

Quindi nel codice in cui vuoi vedere cosa sta succedendo

pdb.set_trace()

e vieni lanciato in un prompt


2
Sto programmando in Python da oltre un decennio. Ci sono così tante volte che avrei potuto usare questo! Non riesco a credere che lo sto scoprendo proprio ora.
hosford42,

1
Come si collega questo where?
skia.heliou,

4
Per rispondere alla parte "dove" della domanda: Dopo aver ricevuto il prompt pdb, (pdb) basta digitare wheree stamperà la traccia dello stack sul terminale.
stephenmm,

1
Python 3.7 e versioni successive hanno una funzione integrata breakpoint()che ovvia alla necessità di importare pdb.
user650654,

6

per chi ha bisogno di stampare lo stack di chiamate mentre usa pdb, basta farlo

(Pdb) where

2

Ecco una variante dell'eccellente risposta di @ RichieHindle che implementa un decoratore che può essere applicato selettivamente alle funzioni come desiderato. Funziona con 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())

Uscita dal campione:

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

Ho scritto la mia versione di decoratore prima di vederlo. Upvoted.
Sida Zhou,

0

Installa Inspect-it

pip3 install inspect-it --user

Codice

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()])

puoi creare uno snippet di questa riga

ti mostrerà un elenco dello stack di chiamate di funzione con un nome file e un numero di linea

elenco dall'inizio a dove metti questa linea

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.