简体   繁体   English

如何在 Python 中获取完整的异常堆栈跟踪

[英]How to get a complete exception stack trace in Python

The following snippet:以下片段:

import traceback

def a():
    b()

def b():
    try:
        c()
    except:
        traceback.print_exc()

def c():
    assert False

a()

Produces this output:产生这个输出:

Traceback (most recent call last):
  File "test.py", line 8, in b
    c()
  File "test.py", line 13, in c
    assert False
AssertionError

What should I use if I want the complete stack trace including the call to a?如果我想要完整的堆栈跟踪,包括对 a 的调用,我应该使用什么?

If it matters I have Python 2.6.6如果重要的话,我有 Python 2.6.6

edit: What I'd like to get is the same information I'd get if I left the try except out and let the exception propagate to the top level.编辑:如果我将 try 排除在外并让异常传播到顶层,我想要得到的信息与我得到的信息相同。 This snippet for example:这个片段例如:

def a():
    b()

def b():
    c()

def c():
    assert False

a()

Produces this output:产生这个输出:

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

Here's a function based on this answer .这是基于此答案的功能。 It will also work when no exception is present:当不存在异常时,它也将起作用:

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() will print the full stack trace up to the top, including eg IPython's interactiveshell.py calls, since there is (to my knowledge) no way of knowing who would catch exceptions. print full_stack()将打印到顶部的完整堆栈跟踪,包括例如IPython 的interactiveshell.py调用,因为(据我所知)没有办法知道谁会捕获异常。 It's probably not worth figuring out anyway...无论如何,这可能不值得弄清楚......

If print full_stack() is called from within an except block, full_stack will include the stack trace down to the raise .如果从一个except块中调用print full_stack()full_stack将包括一直到raise的堆栈跟踪。 In the standard Python interpreter, this will be identical to the message you receive when not catching the exception (Which is why that del stack[-1] is there, you don't care about the except block but about the try block).在标准 Python 解释器中,这将与您在未捕获异常时收到的消息相同(这就是为什么del stack[-1]存在的原因,您不关心except块而是关心try块)。

I don't know if there is a better way, but here's what I did:我不知道是否有更好的方法,但这是我所做的:

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()

And here's the output I get:这是我得到的输出:

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

Use

 traceback.print_stack()

http://docs.python.org/library/traceback.html#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()


Here is a bit better variant of Tobias Kienzler answer .这是Tobias Kienzler answer 的一个更好的变体。 It works same, but can be called not right in except block, but somewhere deeper.它的工作原理相同,但不能在except块中调用,而是在更深的地方调用。 In other words, this variant will print same stacks, when called like换句话说,这个变体将打印相同的堆栈,当调用时

try:
   ...
except Exception:
    print full_stack()

or或者

def print_full_stack():
    print full_stack()

try:
   ...
except Exception:
    print_full_stack()

Here is code:这是代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM