16

有一些类似的问题,但没有一个提供我需要的答案。

如果我通过创建线程threading.Thread,然后抛出未处理的异常,则这些线程将被终止。我希望使用堆栈跟踪保留异常详细信息的默认打印,但也要降低整个过程。

我考虑过可以捕获线程中的所有异常,然后在主线程对象上重新引发它们,或者可以手动执行默认异常处理,然后SystemExit在主线程上引发 a。

解决这个问题的最佳方法是什么?

4

3 回答 3

18

我写了关于在 Python 中重新抛出异常的文章,其中包括非常类似的例子。

在您的工作线程上执行此操作(Python 3.x,请参阅下面的 Python 2.x 版本):

try:
    self.result = self.do_something_dangerous()
except Exception as e:
    import sys
    self.exc_info = sys.exc_info()

在你的主线程上:

if self.exc_info:
    raise self.exc_info[1].with_traceback(self.exc_info[2])
return self.result

Python 2.x:

try:
    self.result = self.do_something_dangerous()
except Exception, e:
    import sys
    self.exc_info = sys.exc_info()

在你的主线程上你这样做:

if self.exc_info:
    raise self.exc_info[1], None, self.exc_info[2]
return self.result

异常将出现在主线程中,就像它已在工作线程中引发一样。

于 2009-12-06T03:39:43.267 回答
12

辅助线程可以可靠地在主线程中引发的唯一例外是KeyboardInterrupt:辅助线程执行此操作的方式是调用函数thread.interrupt_main()。没有办法将额外信息(关于异常的原因)与引发的异常对象相关联——后者总是只是一个普通的KeyboardInterrupt. 因此,您需要将该信息隐藏在其他地方,例如在Queue.Queue的专用实例上——该信息可能包括辅助线程可以通过 获得的结果sys.exc_info(),以及您认为有用的任何其他内容。

主线程将需要恢复那些额外的信息(并考虑到如果键盘中断实际上是由于用户点击 control-C 或类似的,则队列将为空,因此,使用get_nowait并准备好处理Queue.Empty异常,例如),根据需要对其进行格式化,然后终止(如果所有辅助线程都是daemon,则整个进程在主线程终止时终止)。

于 2009-12-06T19:39:40.170 回答
5

非常不幸的是,接受的答案没有回答这个问题。您宁愿将异常详细信息通过管道传输到队列中。请看:Catch a thread's exception in the caller thread in Python

于 2015-04-05T09:14:38.030 回答