如何在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
如果我想要完整的错误追踪信息,包括调用到a的部分,我应该使用什么?
顺便说一下,我使用的是Python 2.6.6
编辑:我想要的结果是,如果我不使用try except,让错误直接抛到最上层时得到的信息。这段代码举个例子:
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
4 个回答
12
使用
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()
38
这里有一个函数,基于这个答案。即使没有异常发生,它也能正常工作:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
if exc is not None: # i.e. 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 exc is not None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr
print full_stack()
这个命令会打印出完整的调用栈信息,一直到最上层,包括像IPython的interactiveshell.py
这样的调用。因为据我所知,没有办法知道谁会捕获异常,所以这部分信息是很重要的。其实,搞清楚这些也没什么太大意义……
如果在except
块中调用print full_stack()
,那么full_stack
会显示从异常抛出到捕获的整个调用栈。在标准的Python解释器中,这个信息和你在没有捕获异常时收到的消息是一样的(这就是为什么有del stack[-1]
这行代码,因为你不关心except
块的内容,而是try
块的内容)。
26
我不知道有没有更好的方法,但这是我做的:
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