python 在主线程的线程中引发未处理的异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1854216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Raise unhandled exceptions in a thread in the main thread?
提问by Matt Joiner
There are some similar questions, but none supply the answer I require.
有一些类似的问题,但没有一个提供我需要的答案。
If I create threads via threading.Thread
, which then throw exceptions which are unhandled, those threads are terminated. I wish to retain the default print out of the exception details with the stack trace, but bring down the whole process as well.
如果我通过创建线程threading.Thread
,然后抛出未处理的异常,这些线程将被终止。我希望使用堆栈跟踪保留异常详细信息的默认打印,但也要降低整个过程。
I've considered that it might be possible to catch all exceptions in the threads, and reraise them on the main thread object, or perhaps it's possible to manually perform the default exception handling, and then raise a SystemExit
on the main thread.
我认为有可能捕获线程中的所有异常,并在主线程对象上重新引发它们,或者可能可以手动执行默认异常处理,然后SystemExit
在主线程上引发 a 。
What's the best way to go about this?
解决这个问题的最佳方法是什么?
回答by Ned Batchelder
I wrote about Re-throwing exceptions in Python, including something very much like this as an example.
我写了关于在 Python 中重新抛出异常,包括非常像这样的例子。
On your worker thread you do this (Python 2.x, see below for Python 3.x version):
在您的工作线程上执行此操作(Python 2.x,Python 3.x 版本见下文):
try:
self.result = self.do_something_dangerous()
except Exception, e:
import sys
self.exc_info = sys.exc_info()
and on your main thread you do this:
在你的主线程上你这样做:
if self.exc_info:
raise self.exc_info[1], None, self.exc_info[2]
return self.result
The exception will appear in the main thread just as if it had been raised in the worker thread.
异常将出现在主线程中,就像它是在工作线程中引发的一样。
Python 3.x:
Python 3.x:
try:
self.result = self.do_something_dangerous()
except Exception as e:
import sys
self.exc_info = sys.exc_info()
and on your main thread:
并在您的主线程上:
if self.exc_info:
raise self.exc_info[1].with_traceback(self.exc_info[2])
return self.result
回答by Alex Martelli
The only exception a secondary thread can reliably raise in the main thread is KeyboardInterrupt
: the way the secondary thread does it is by calling the function thread.interrupt_main()
. There is no way to associate extra info (about the reason for the exception) with the exception object that gets raised -- the latter's always just a plain KeyboardInterrupt
. So, you need to stash that information away somewhere else, e.g. on a dedicated instance of Queue.Queue-- that info might include the results the secondary thread can get via sys.exc_info()
, and anything else you find useful of course.
辅助线程可以在主线程中可靠地引发的唯一例外是KeyboardInterrupt
:辅助线程通过调用函数来执行此操作thread.interrupt_main()
。无法将额外信息(关于异常的原因)与引发的异常对象相关联——后者总是一个普通的KeyboardInterrupt
. 因此,您需要将该信息隐藏在其他地方,例如,在Queue.Queue的专用实例上——该信息可能包括辅助线程可以通过的结果sys.exc_info()
,以及您认为有用的任何其他内容。
The main thread will need to recover that extra info (and take into account that the queue will be empty if the keyboard interrupt is actually due to the user hitting control-C or the like, so, use get_nowait
and be ready to deal with a Queue.Empty
exception, for example), format it however you desire, and terminate (if all secondary threads are daemons, the whole process terminates when the main thread terminates).
主线程将需要恢复那些额外的信息(并考虑到如果键盘中断实际上是由于用户点击 control-C 或类似的原因,队列将为空,因此,使用get_nowait
并准备好处理Queue.Empty
异常,例如),根据需要对其进行格式化,然后终止(如果所有辅助线程都是daemon,则整个进程在主线程终止时终止)。
回答by Christophe
Very unfortunately the accepted answer does not answer the question. You would rather pipe the exception details into a Queue. Please have a look at: Catch a thread's exception in the caller thread in Python
非常不幸的是,接受的答案并没有回答这个问题。您宁愿将异常详细信息通过管道传输到队列中。请看一看:Catch a thread's exception in the caller thread in Python