有一些类似的问题,但没有一个能提供我需要的答案。
如果我通过threading.Thread
创建线程,然后这些线程抛出未处理的异常,那么这些线程将被终止。我希望保留异常详细信息和堆栈跟踪的默认打印输出,同时也使整个进程崩溃。
我考虑过在线程中捕获所有异常,并在主线程对象上重新引发它们,或者手动执行默认的异常处理,然后在主线程上引发SystemExit
。
最佳方法是什么?
有一些类似的问题,但没有一个能提供我需要的答案。
如果我通过threading.Thread
创建线程,然后这些线程抛出未处理的异常,那么这些线程将被终止。我希望保留异常详细信息和堆栈跟踪的默认打印输出,同时也使整个进程崩溃。
我考虑过在线程中捕获所有异常,并在主线程对象上重新引发它们,或者手动执行默认的异常处理,然后在主线程上引发SystemExit
。
最佳方法是什么?
我写了关于在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
KeyboardInterrupt
:次要线程这样做的方式是调用函数thread.interrupt_main()
。没有办法将额外的信息(关于异常原因)与被引发的异常对象相关联 - 后者总是一个普通的KeyboardInterrupt
。因此,您需要将该信息存储在其他地方,例如专用实例的Queue.Queue上 - 该信息可能包括次要线程可以通过sys.exc_info()
获得的结果,以及您找到的任何其他有用信息。get_nowait
并准备处理Queue.Empty
异常,例如),以任何所需的格式进行格式化,并终止(如果所有次要线程都是daemons,则当主线程终止时,整个进程终止)。
thrdobj.exc_info
,为什么重新抛出时要丢弃异常类型? - Matt Joinerself
的问题仍然存在,感谢你提供了一个好答案,我会尝试一下的。 - Matt Joinerjoin()
时,自动重新引发异常。 - ejm