有一些类似的问题,但没有一个能提供我需要的答案。
如果我通过threading.Thread
创建线程,然后抛出未处理的异常,则终止这些线程。我希望使用堆栈跟踪保留缺省打印的异常详细信息,但也要关闭整个过程。
我认为有可能捕获线程中的所有异常,并在主线程对象上重新加载它们,或者可能手动执行默认的异常处理,然后引发SystemExit
在主线上。
最好的方法是什么?
答案 0 :(得分:16)
我写过关于Re-throwing exceptions in Python的文章,包括非常类似的例子。
在您的工作线程上执行此操作(Python 2.x,请参阅下面的Python 3.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
异常将出现在主线程中,就像它已在工作线程中引发一样。
Python 3.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
答案 1 :(得分:10)
辅助线程可以在主线程中可靠地引发的唯一例外是KeyboardInterrupt
:辅助线程执行此操作的方式是调用函数thread.interrupt_main()
。没有办法将额外的信息(关于异常的原因)与引发的异常对象相关联 - 后者总是只是一个普通的KeyboardInterrupt
。因此,您需要将该信息存储在其他地方,例如在Queue.Queue的专用实例上 - 该信息可能包括辅助线程可以通过sys.exc_info()
获得的结果,以及您认为有用的任何其他内容。
主线程将需要恢复该额外信息(并考虑到如果键盘中断实际上是由于用户点击control-C等而队列将为空,那么,使用get_nowait
并且准备好处理例如Queue.Empty
异常,根据需要对其进行格式化,并终止(如果所有辅助线程都是daemon,则整个进程在主线程终止时终止)。
答案 2 :(得分:3)
非常不幸的是,接受的答案没有回答这个问题。您宁愿将异常详细信息传递到队列中。请查看:Catch a thread's exception in the caller thread in Python