2009-12-06 64 views
12

有一些类似的问题,但没有提供我所需要的答案。在主线程的线程中引发未处理的异常?

如果我通过创建线程threading.Thread,然后抛出异常,这是未处理的,这些线程被终止。我希望通过堆栈跟踪保留默认打印的例外细节,但是也会拖延整个过程。

我认为有可能捕获线程中的所有异常,并将它们重新显示在主线程对象上,或者也许可以手动执行缺省异常处理,然后在主体上引发一个SystemExit线。

这是什么最好的方法呢?

回答

15

我写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 
+0

您是不是故意在主线程中抛出'thrdobj.exc_info',为什么在重新抛出时抛出异常类型呢? – 2009-12-06 05:34:33

+0

我现在看到的,不得不对3arg raise语句读了。但关于“自我”的问题仍然存在,感谢一个好的答案,我会试试 – 2009-12-06 05:37:27

+0

我不确定你对自己的问题是什么。此代码来自用于将工作推迟到工作线程的对象,因此同一对象在工作线程和主线程中运行代码。 – 2009-12-06 13:00:58

9

唯一例外的辅助线程可以在主线程中可靠地提高为KeyboardInterrupt:一路辅助线程是通过调用函数thread.interrupt_main()来实现的。有没有办法来额外的信息(关于异常的原因)与被引起的异常对象联系起来 - 后者总是只是一个普通的KeyboardInterrupt。所以,你需要将这些信息存储在其他地方,例如,在Queue.Queue的专用实例上 - 该信息可能包括次要线程可通过sys.exc_info()获得的结果,以及其他任何您认为有用的结果。

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

+0

已更新的线程文档链接:https://docs.python.org/3.6/library/_thread.html?highlight = interrupt_main#_thread.interrupt_main – user2682863 2017-11-25 15:57:40