Как получить полную трассировку стека исключений в Python
Следующий фрагмент:
import traceback
def a():
b()
def b():
try:
c()
except:
traceback.print_exc()
def c():
assert False
a()
Производит этот вывод:
Traceback (most recent call last):
File "test.py", line 8, in b
c()
File "test.py", line 13, in c
assert False
AssertionError
Что следует использовать, если я хочу, чтобы полная трассировка стека включала вызов?
Если это имеет значение, у меня есть Python 2.6.6
edit: То, что я хотел бы получить, - это та же самая информация, которую я получил бы, если бы я оставил попытку, кроме исключения, и пусть исключение распространяется на верхний уровень. Этот фрагмент, например:
def a():
b()
def b():
c()
def c():
assert False
a()
Производит этот вывод:
Traceback (most recent call last):
File "test.py", line 10, in <module>
a()
File "test.py", line 2, in a
b()
File "test.py", line 5, in b
c()
File "test.py", line 8, in c
assert False
AssertionError
Ответы
Ответ 1
Я не знаю, есть ли лучший способ, но вот что я сделал:
import traceback
import sys
def format_exception(e):
exception_list = traceback.format_stack()
exception_list = exception_list[:-2]
exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))
exception_str = "Traceback (most recent call last):\n"
exception_str += "".join(exception_list)
# Removing the last \n
exception_str = exception_str[:-1]
return exception_str
def main1():
main2()
def main2():
try:
main3()
except Exception as e:
print "Printing only the traceback above the current stack frame"
print "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
print
print "Printing the full traceback as if we had not caught it here..."
print format_exception(e)
def main3():
raise Exception()
if __name__ == '__main__':
main1()
И вот результат, который я получаю:
Printing only the traceback above the current stack frame
Traceback (most recent call last):
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Printing the full traceback as if we had not caught it here...
Traceback (most recent call last):
File "exc.py", line 34, in <module>
main1()
File "exc.py", line 18, in main1
main2()
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Ответ 2
Здесь функция, основанная на этом ответе. Он также будет работать, если не будет никакого исключения:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
if not exc is None: # i.e. if an exception is present
del stack[-1] # remove call of full_stack, the printed exception
# will contain the caught exception caller instead
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if not exc is None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr
print full_stack()
будет печатать полную трассировку стека до вершины, включая, например, IPython interactiveshell.py
вызывает, поскольку, насколько мне известно, нет способа узнать, кто будет ловить исключения. Это, вероятно, не стоит выяснять в любом случае...
Если print full_stack()
вызывается из блока except
, full_stack
будет содержать трассировку стека до raise
. В стандартном интерпретаторе Python это будет идентично сообщению, которое вы получите, когда не поймаете исключение (поэтому это del stack[-1]
есть, вам не нужен блок except
, а блок try
).
Ответ 3
Использование
traceback.print_stack()
http://docs.python.org/library/traceback.html#traceback.print_stack
suxmac2 $ python out.py
File "out.py", line 16, in <module>
a()
File "out.py", line 5, in a
b()
File "out.py", line 11, in b
traceback.print_stack()
Ответ 4
Вот немного лучший вариант ответа Тобиас Киенцлер. Он работает так же, но может быть назван не правильным в блоке except
, но где-то глубже.
Другими словами, этот вариант будет печатать одинаковые стеки, когда вызывается как
try:
...
except Exception:
print full_stack()
или
def print_full_stack():
print full_stack()
try:
...
except Exception:
print_full_stack()
Вот код:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
if exc is not None:
f = sys.exc_info()[-1].tb_frame.f_back
stack = traceback.extract_stack(f)
else:
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if exc is not None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr