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