W języku Python, w jaki sposób mogę wydrukować bieżący stos wywołań z metody (w celu debugowania).Drukuj bieżący stos wywołań z metody w kodzie Python
Odpowiedz
Oto przykład na uzyskanie stosu poprzez moduł traceback i drukowanie go:
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():
Jeśli naprawdę tylko chcesz wydrukować stos na stderr, można użyć:
traceback.print_stack()
lub wydrukować na standardowe wyjście (przydatne, jeśli chce zachować przekierowany razem), zastosowanie:
traceback.print_stack(file=sys.stdout)
Ale uzyskanie go przez traceback.format_stack()
pozwala ci robić, co chcesz z tym.
import traceback
traceback.print_stack()
Właściwie, lubię 'traceback.print_exc()', które daje prawie to samo, co dostałeśby bez instrukcji 'except' (i jest również mniej kodowania niż zaakceptowana odpowiedź). – martineau
'traceback.print_exc()' wyświetla ślad stosu dla dowolnego wyjątku, który może być obsługiwany - ale to nie rozwiązuje pierwotnego pytania, które polega na drukowaniu stosu _current_ ("gdzie teraz jesteś" w przeciwieństwie do "gdzie Twój kod był, gdy ostatni wyjątek wyszedł, jeśli w ogóle ".) –
inspect.stack()
zwraca bieżące stos zamiast stosie z wyjątek:
import inspect
print inspect.stack()
Patrz https://gist.github.com/FredLoney/5454553 dla funkcji użytkowych log_stack.
Jeśli używasz debuggera python, nie tylko interaktywne sondowanie zmiennych, ale możesz uzyskać stos wywołań za pomocą komendy "where" lub "w".
Więc na początku programu
import pdb
następnie w kodzie, w którym chcesz, aby zobaczyć co się dzieje
pdb.set_trace()
i zrzucane do szybkiego
Programuję w Pythonie od ponad dekady. Są * tak * wiele razy mogłem tego użyć! Nie mogę uwierzyć, że właśnie się o tym dowiedziałem. – hosford42
Oto odmiana doskonałej odpowiedzi @ RichieHindle, która implementuje dekorator, który można selektywnie zastosować do funkcji według potrzeb. Działa z Python 2.7.14 i 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())
Wyjście z próbką:
test_func() called:
File "stacktrace_decorator.py", line 28, in <module>
print(test_func())
42
Jako wyrażenie: 'stack_str = '' .join (traceback.format_stack())' – scottmrogowski
Jak zrobić to samo dla wszystkich innych wątków * (I” m mówienie o wątkach, których nie kontroluję) *? – user2284570
Może brakuje mi tutaj czegoś, ale nazywasz f, którego jedynym celem jest tutaj wywołanie g i nie robi nic innego. Dlaczego – Chris