重新引发Python异常并保留堆栈跟踪

时间:2012-01-06 15:34:30

标签: python exception stack-trace

我正在尝试在线程中捕获异常并在主线程中重新引发它:

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>

3 个答案:

答案 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?