33

以下片段:

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

编辑:我想获得的是相同的信息,如果我离开尝试除外,让异常传播到顶层。这个片段例如:

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

4 回答 4

31

这是基于此答案的功能。当不存在异常时它也可以工作:

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调用,因为(据我所知)无法知道谁会捕获异常。反正估计也不值得去想...

如果从块print full_stack()内调用,将包括堆栈跟踪到. 在标准的 Python 解释器中,这将与您在未捕获异常时收到的消息相同(这就是为什么存在,您不关心块,而是关心块)。exceptfull_stackraisedel stack[-1]excepttry

于 2013-05-16T14:04:47.590 回答
22

我不知道是否有更好的方法,但这是我所做的:

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
于 2012-09-21T23:21:35.263 回答
11

利用

 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()
于 2011-05-22T09:16:49.540 回答
5


这是Tobias Kienzler answer的一个更好的变体。它的工作原理相同,但不能直接在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
于 2017-11-12T09:14:35.293 回答