Raise unhandled exceptions in a thread in the main thread?
Solution 1
I wrote about Re-throwing exceptions in Python, including something very much like this as an example.
On your worker thread you do this (Python 3.x, see below for Python 2.x version):
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
Python 2.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.
Solution 2
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.
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).
Solution 3
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
Matt Joiner
About Me I like parsimonious code, with simple interfaces and excellent documentation. I'm not interested in enterprise, boiler-plate, or cookie-cutter nonsense. I oppose cruft and obfuscation. My favourite languages are Go, Python and C. I wish I was better at Haskell. Google+ GitHub Bitbucket Google code My favourite posts http://stackoverflow.com/questions/3609469/what-are-the-thread-limitations-when-working-on-linux-compared-to-processes-for/3705919#3705919 http://stackoverflow.com/questions/4352425/what-should-i-learn-first-before-heading-to-c/4352469#4352469 http://stackoverflow.com/questions/6167809/how-much-bad-can-be-done-using-register-variables-in-c/6168852#6168852 http://stackoverflow.com/questions/4141307/c-and-c-source-code-profiling-tools/4141345#4141345 http://stackoverflow.com/questions/3463207/how-big-can-a-malloc-be-in-c/3486163#3486163 http://stackoverflow.com/questions/4095637/memory-use-of-stl-data-structures-windows-vs-linux/4183178#4183178
Updated on February 11, 2022Comments
-
Matt Joiner over 2 years
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.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.What's the best way to go about this?
-
Matt Joiner over 14 yearsdon't you mean to throw
thrdobj.exc_info
in the main thread, and why drop the exception type when you rethrow? -
Matt Joiner over 14 yearsi see now, had to read up on 3arg raise statement. but the question about
self
still stands, thanks for a good answer, i'll try it out -
yantrab over 14 yearsI'm not sure what your question about self is. This code came from an object that is used to defer work onto a worker thread, so the same object runs code in the worker and main threads.
-
Robert Rossney over 14 yearsI suspect the issue is not so much the mechanics of knowing how to re-raise the exception as when to, i.e. how does the main thread know that there's an exception waiting to be re-raised?
-
ejm over 6 yearsThis answer stackoverflow.com/a/12223550 shows a nice way to encapsulate this into your Thread implementation, automatically re-raising the exception in the main thread when it calls
join()
on the worker thread. -
user2682863 over 6 yearsupdated threading documentation link: docs.python.org/3.6/library/…