虽然不可能直接捕获在不同线程中抛出的异常,但下面的代码可以非常透明地获取与此功能非常接近的内容。子线程必须将ExThread类而不是threading.Thread父线程必须调用child_thread.join_with_exception()方法而不是child_thread.join()当等待线程完成其工作时。
此实现的技术细节:当子线程抛出异常时,将通过Queue并再次抛出父线程。注意,在这种方法中没有繁忙的等待。#!/usr/bin/env pythonimport sysimport threadingimport Queueclass 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 BaseException:
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_info[1]class MyException(Exception):
passclass 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()