我正在尝试在线程中捕获异常并在主线程中重新引发它:
import threading
import sys
class FailingThread(threading.Thread):
def run(self):
try:
raise ValueError('x')
except ValueError:
self.exc_info = sys.exc_info()
failingThread = FailingThread()
failingThread.start()
failingThread.join()
print failingThread.exc_info
raise failingThread.exc_info[1]
这基本上起作用并产生以下输出:
(<type 'exceptions.ValueError'>, ValueError('x',), <traceback object at 0x1004cc320>)
Traceback (most recent call last):
File "test.py", line 16, in <module>
raise failingThread.exc_info[1]
然而,异常的来源指向第16行,其中发生了重新加注。原始异常来自第7行。如何修改 main 线程,使输出显示为:
Traceback (most recent call last):
File "test.py", line 7, in <module>
答案 0 :(得分:51)
在Python 2中,您需要使用所有三个参数来提升:
raise failingThread.exc_info[0], failingThread.exc_info[1], failingThread.exc_info[2]
将traceback对象作为第三个参数传递,保留堆栈。
来自help('raise')
:
如果存在第三个对象而不是
None
,则它必须是回溯 对象(参见标准类型层次结构部分),它是 替换当前位置而不是当前位置 异常发生。如果第三个对象存在而不是a 追溯对象或None
,引发TypeError
异常。该raise
的三表达形式对于重新引发异常很有用 透明地在except子句中,但raise
没有表达式 如果重新提出的例外最多,则应该优先考虑 最近在当前范围内的活动例外。
在这种特殊情况下,您不能使用no表达式版本。
对于Python 3(根据评论):
raise failingThread.exc_info[1].with_traceback(failingThread.exc_info[2])
或者您可以使用raise ... from ...
简单地链接例外,但是会在原因属性中附加原始上下文时引发链接异常,这可能是也可能不是您想要的。< / p>
答案 1 :(得分:1)
此代码段适用于python 2&amp; 3:
1 try:
----> 2 raise KeyError('Default key error message')
3 except KeyError as e:
4 e.args = ('Custom message when get re-raised',) #The comma is not a typo, it's there to indicate that we're replacing the tuple that e.args pointing to with another tuple that contain the custom message.
5 raise
答案 2 :(得分:0)
你能写得有点像这样:
try:
raise ValueError('x')
except ValueError as ex:
self.exc_info = ex
然后使用异常中的stacktrace?