The problem is that thread_obj.start() returns immediately. The child thread that you spawned executes in its own context, with its own stack. Any exception that occurs there is in the context of the child thread, and it is in its own stack.
One way I can think of right now to communicate this information to the parent thread is by using some sort of message passing, so you might look into that Try this on for size: import sys import threading import Queue class ExcThread(threading. Thread): def __init__(self, bucket): threading.Thread. __init__(self) self.
Bucket = bucket def run(self): try: raise Exception('An error occured here. ') except Exception: self.bucket. Put(sys.
Exc_info()) def main(): bucket = Queue.Queue() thread_obj = ExcThread(bucket) thread_obj.start() while True: try: exc = bucket. Get(block=False) except Queue. Empty: pass else: exc_type, exc_obj, exc_trace = exc # deal with the exception print exc_type, exc_obj print exc_trace thread_obj.
Join(0.1) if thread_obj.isAlive(): continue else: break if __name__ == '__main__': main().
The problem is that thread_obj.start() returns immediately. The child thread that you spawned executes in its own context, with its own stack. Any exception that occurs there is in the context of the child thread, and it is in its own stack.
One way I can think of right now to communicate this information to the parent thread is by using some sort of message passing, so you might look into that. Try this on for size: import sys import threading import Queue class ExcThread(threading. Thread): def __init__(self, bucket): threading.Thread.
__init__(self) self. Bucket = bucket def run(self): try: raise Exception('An error occured here. ') except Exception: self.bucket.
Put(sys. Exc_info()) def main(): bucket = Queue.Queue() thread_obj = ExcThread(bucket) thread_obj.start() while True: try: exc = bucket. Get(block=False) except Queue.
Empty: pass else: exc_type, exc_obj, exc_trace = exc # deal with the exception print exc_type, exc_obj print exc_trace thread_obj. Join(0.1) if thread_obj.isAlive(): continue else: break if __name__ == '__main__': main().
This looks like it will work. I will need to try this when I get a chance. For now, I'm marking your post as the answer.
Thank you! – Phanto May 13 '10 at 23:17 I just tried this, and it does work. Thank you!
:) – Phanto May 13 '10 at 23:40.
You have to think of threads in terms of phone calls. Consider this. You call up the local city council and ask a question.
While they find the answer for you, you hold. When they have the answer, they'll tell it to you, and then you hang up. If for some reason they can't find the answer (exception), they will tell you that.
This is how a synchronous, normal, method call works. You call a method, when it returns, you have the answer (good or bad. ) However, a thread goes more like this: You call up the local city council and ask a question, and ask them to call you back when they have the answer.
You then hang up. At this point, you don't know if they will find the answer or not, so any attempt, now, to try to handle the result of the inquiry, will fail, as you simply don't have the results yet. Instead, you have to react to the incoming call, and take the news, good or bad, and then process it.In terms of your code, you need to have code that reacts to your thread failing, and logs or processes the exception.
The code you have in your question, which you say doesn't work, is just like trying to process the results of the phone call right after hanging up, when you still don't have the answer.
2 That is perhaps one of the best explanations of multithreading I have ever read. If my reputation were higher, I would definitely uprank your post. – Phanto May 13 '10 at 23:16.
Although it is not possible to directly catch an exception thrown in a different thread, here's a code to quite transparently obtain something very close to this functionality. Your child thread must subclass the ExThread class instead of threading. Thread and the parent thread must call the child_thread.
Join_with_exception() method instead of child_thread.join() when waiting for the thread to finish its job. Technical details of this implementation: when the child thread throws an exception, it is passed to the parent through a Queue and thrown again in the parent thread. Notice that there's no busy waiting in this approach .
#! /usr/bin/env python import sys import threading import Queue class ExThread(threading. Thread): def __init__(self): threading.Thread.
__init__(self) self. __status_queue = Queue.Queue() def run_with_exception(self): """This method should be overriden. """ raise NotImplementedError def run(self): """This method should NOT be overriden.""" try: self.
Run_with_exception() except Exception: self. __status_queue. Put(sys.
Exc_info()) self. __status_queue. Put(None) def wait_for_exc_info(self): return self.
__status_queue.get() def join_with_exception(self): ex_info = self. Wait_for_exc_info() if ex_info is None: return else: raise ex_info1 class MyException(Exception): pass class MyThread(ExThread): def __init__(self): ExThread. __init__(self) def run_with_exception(self): thread_name = threading.
Current_thread(). Name raise MyException("An error in thread '{}'.". Format(thread_name)) def main(): t = MyThread() t.start() try: t.
Join_with_exception() except MyException as ex: thread_name = threading. Current_thread(). Name print "Caught a MyException in thread '{}': {}".
Format(thread_name, ex) if __name__ == '__main__': main().
Using naked excepts is not a good practice because you usually catch more than you bargain for. I would suggest modifying the except to catch ONLY the exception that you would to handle. I don't think that raising it has the desired effect, because when you go to instantiate TheThread in the outer try, if it raises an exception, the assignment is never going to happen.
Instead you might want to just alert on it and move on, such as: def run(self): try: shul. Copytree(self. SourceFolder, self.
DestFolder) except OSError, err: print err Then when that exception is caught, you can handle it there. Then the outer try catches an exception from TheThread, you know it won't be the one you already handled, and will help you isolate your process flow.
Well, if there is an error in that thread at all, I want the full program to inform the user that there was an issue and gracefully end. For that reason, I want the main thread to catch and handle all the exceptions. However, the problem still exists where if TheThread throws an exception, the main thread's try/except still won't catch it.
I could have the thread detect the exception and return a false indicating that the operation was unsuccessful. That would achieve the same desired result, but I would still like to know how to properly catch a sub-thread exception. – Phanto May 13 '10 at 19:35.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.