Druckt den aktuellen Aufrufstapel von einer Methode in Python-Code

276

Wie kann ich in Python den aktuellen Aufrufstapel aus einer Methode heraus drucken (zu Debugging-Zwecken)?

man selbst
quelle

Antworten:

319

Hier ist ein Beispiel, wie Sie den Stapel über das Traceback- Modul abrufen und drucken können:

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

Wenn Sie den Stapel wirklich nur auf stderr drucken möchten, können Sie Folgendes verwenden:

traceback.print_stack()

Oder verwenden Sie zum Drucken auf Standardausgabe (nützlich, wenn Sie die umgeleitete Ausgabe zusammenhalten möchten):

traceback.print_stack(file=sys.stdout)

Aber traceback.format_stack()wenn Sie es über bekommen, können Sie damit machen, was Sie wollen.

RichieHindle
quelle
Wie mache ich dasselbe für alle anderen Threads (ich spreche von Threads, die ich nicht kontrolliere)  ?
user2284570
Vielleicht fehlt mir hier etwas, aber du rufst f an, was nur dazu dient, g anzurufen und nichts anderes zu tun. Warum
Chris
6
@ Chris: Es ist nur ein Beispiel. Es hat mehrere Funktionen, um zu verdeutlichen, dass format_stack () alle Aufrufe auf dem Stapel druckt.
RichieHindle
Wenn Sie eine ausführlichere Ausgabe erhalten möchten (einschließlich vars usw.), lesen Sie diese und diese Frage .
Albert
@ user2284570: Sie können verwenden sys._current_frames(). Zumdump_all_thread_tracebacks Beispiel macht py_better_exchook das (Haftungsausschluss: Das habe ich geschrieben).
Albert
93
import traceback
traceback.print_stack()
Mark Roddy
quelle
8
Eigentlich gefällt mir traceback.print_exc(), was Ihnen fast das gleiche gibt, was Sie ohne die exceptAussage bekommen hätten (und auch weniger codiert als die akzeptierte Antwort).
Martineau
34
traceback.print_exc()druckt die Stapelverfolgung für jede Ausnahme, die Sie möglicherweise behandeln - dies löst jedoch nicht die ursprüngliche Frage, wie der aktuelle Stapel gedruckt werden soll ("wo Sie sich jetzt befinden" im Gegensatz zu "wo sich Ihr Code befand, als die letzte Ausnahme aufgetreten ist" aus, wenn überhaupt ".)
Tom Swirly
17

Wenn Sie den Python-Debugger verwenden, können Sie nicht nur Variablen interaktiv prüfen, sondern den Aufrufstapel auch mit dem Befehl "where" oder "w" abrufen.

Also ganz oben in Ihrem Programm

import pdb

Dann im Code, wo Sie sehen möchten, was passiert

pdb.set_trace()

und Sie werden in eine Eingabeaufforderung fallen gelassen

Keir
quelle
2
Ich programmiere seit über einem Jahrzehnt in Python. Es gibt so viele Male, die ich hätte benutzen können! Ich kann nicht glauben, dass ich es gerade herausfinde.
Hosford42
1
Wie hängt das zusammen where?
skia.heliou
4
So beantworten Sie den "Wo" -Teil der Frage: Nachdem Sie die pdb-Eingabeaufforderung erhalten haben, geben Sie (pdb) einfach ein whereund der Stack-Trace wird auf dem Terminal gedruckt.
Stephenmm
1
Python 3.7 und höher verfügt über eine integrierte Funktion, breakpoint()die den Import von pdb überflüssig macht.
user650654
6

Für diejenigen, die den Aufrufstapel drucken müssen, während sie pdb verwenden, tun Sie dies einfach

(Pdb) where
Maus Ratte
quelle
2

Hier ist eine Variation von @ RichieHindles hervorragender Antwort, die einen Dekorateur implementiert, der selektiv auf gewünschte Funktionen angewendet werden kann. Funktioniert mit Python 2.7.14 und 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())

Ausgabe von Probe:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42
Martineau
quelle
Schrieb meine eigene Dekorationsversion, bevor ich das sah. Upvoted.
Sida Zhou
0

Installieren Sie Inspect-it

pip3 install inspect-it --user

Code

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

Sie können einen Ausschnitt aus dieser Zeile erstellen

Es zeigt Ihnen eine Liste des Funktionsaufrufstapels mit einem Dateinamen und einer Zeilennummer

Liste von Anfang bis wo Sie diese Zeile setzen

MohitGhodasara
quelle