从exception对象中提取回溯信息
鉴于一个exception对象(来源不明)是否有办法获得它的回溯? 我有这样的代码:
def stuff(): try: ..... return useful except Exception as e: return e result = stuff() if isinstance(result, Exception): result.traceback <-- How?
一旦拥有它,我怎样才能从Exception对象中提取回溯?
回溯没有存储在exception中。 (不是,就是在Python 2中,请参阅Vyktor关于Python 3中情况的更多答案)。 在except
子句中,可以使用sys.exc_info()
来检索它。 有关一些有用的工具,请参阅traceback
模块。
>>> import sys, traceback >>> def raise_exception(): ... try: ... raise Exception ... except Exception: ... ex_type, ex, tb = sys.exc_info() ... traceback.print_tb(tb) ... finally: ... del tb ... >>> raise_exception() File "<stdin>", line 3, in raise_exception
或者,你的情况(因为你不能修改try/except
块):
>>> def view_traceback(): ... ex_type, ex, tb = sys.exc_info() ... traceback.print_tb(tb) ... del tb ... >>> try: ... raise Exception ... except Exception: ... view_traceback() ... File "<stdin>", line 2, in <module>
详细说, sys.exc_info
返回当前正在处理的exception的exception,exceptiontypes和回溯。
但是正如你的编辑所指出的那样,如果你的exception在处理完成之后还没有被处理,那么你试图获得已经打印的回溯。 这是一个更难的问题。 “正常”exception不会存储追溯信息,可能是因为保持exception轻量级可以在发生exception时更快地执行。 (另外, ecatmur观察到,在本地variables中存储回溯会创build循环引用。)不幸的是,当没有exception处理时, sys.exc_info
返回(None, None, None)
。 其他相关的sys
属性也没有帮助。 sys.exc_traceback
被弃用,未定义,当没有exception处理; sys.last_traceback
看起来很完美,但我相信只能在交互式会话中定义。
如果您可以控制如何引发exception,则可以使用inspect
和自定义exception来存储一些信息。 但我甚至不确定这是如何工作的。
我会补充说, 捕获和返回exception是一种不寻常的事情; 我会build议重构。
从Python 3.0 [PEP 3109]开始 ,内置的Exception
类有一个__traceback__
属性,它包含一个traceback object
(使用Python 3.2.3):
>>> try: ... raise Exception() ... except Exception as e: ... tb = e.__traceback__ ... >>> tb <traceback object at 0x00000000022A9208>
问题是, 谷歌search__traceback__
一段时间后,我发现只有几篇文章,但没有一个描述是否或为什么你应该(不)使用__traceback__
。
不过, Python 3的文档中提到:
回溯对象通常在引发exception时自动创build,并作为可写的
__traceback__
属性附加到它。
所以我认为这是为了使用。
回溯没有存储在exception中有很好的理由。 因为回溯持有引用它的堆栈的本地,这将导致循环引用和(临时)内存泄漏,直到循环GC启动。(这就是为什么你永远不应该存储回溯本地variables 。)
关于我能想到的唯一的事情就是让你monkeypatch stuff
的全局variables,以便当它认为它正在捕获Exception
它实际上捕获一个专门的types和exception传播给你作为调用者:
module_containing_stuff.Exception = type("BogusException", (Exception,), {}) try: stuff() except Exception: import sys print sys.exc_info()