2009-07-20 17 views

Odpowiedz

213

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.

+8

Jako wyrażenie: 'stack_str = '' .join (traceback.format_stack())' – scottmrogowski

+0

Jak zrobić to samo dla wszystkich innych wątków * (I” m mówienie o wątkach, których nie kontroluję) *? – user2284570

+0

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

69
import traceback 
traceback.print_stack() 
+6

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

+22

'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 ".) –

8

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

+0

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

0

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 
Powiązane problemy