繁体   English   中英

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

[英]Re-raise Python exception and preserve 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行。如何修改线程以使输出显示:

Traceback (most recent call last):
  File "test.py", line 7, in <module>

在Python 2中,您需要使用所有三个参数来引发:

raise failingThread.exc_info[0], failingThread.exc_info[1], failingThread.exc_info[2]

传递traceback对象作为第三个参数保留堆栈。

来自help('raise')

如果存在第三个对象而不是None ,则它必须是一个回溯对象(请参阅标准类型层次结构一节),并将其替换为当前位置作为发生异常的位置。 如果存在第三个对象而不是回溯对象或None ,则引发TypeError异常。 raise的三表达式形式对于在except子句中透明地重新引发异常很有用,但如果要重新引发的异常是当前作用域中最近活动的异常,则应该首选raise而不使用表达式。

在这种特殊情况下,您不能使用no表达式版本。

对于Python 3(根据评论):

raise failingThread.exc_info[1].with_traceback(failingThread.exc_info[2])

或者您可以使用raise ... from ...简单地链接异常,但是会在原因属性中附加原始上下文引发链接异常,这可能是也可能不是您想要的。

这段代码在python 2和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

你能写得这样吗:

try:
    raise ValueError('x')
except ValueError as ex:
    self.exc_info = ex

然后使用异常中的stacktrace?

暂无
暂无

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

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