Back to index

apport  2.4
REThread.py
Go to the documentation of this file.
00001 '''Enhanced Thread with support for return values and exception propagation.'''
00002 
00003 # Copyright (C) 2007 Canonical Ltd.
00004 # Author: Martin Pitt <martin.pitt@ubuntu.com>
00005 #
00006 # This program is free software; you can redistribute it and/or modify it
00007 # under the terms of the GNU General Public License as published by the
00008 # Free Software Foundation; either version 2 of the License, or (at your
00009 # option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
00010 # the full text of the license.
00011 
00012 import threading, sys
00013 
00014 
00015 class REThread(threading.Thread):
00016     '''Thread with return values and exception propagation.'''
00017 
00018     def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
00019                  verbose=None):
00020         '''Initialize Thread, identical to threading.Thread.__init__().'''
00021 
00022         threading.Thread.__init__(self, group, target, name, args, kwargs, verbose)
00023         self.__target = target
00024         self.__args = args
00025         self.__kwargs = kwargs
00026         self._retval = None
00027         self._exception = None
00028 
00029     def run(self):
00030         '''Run target function, identical to threading.Thread.run().'''
00031 
00032         if self.__target:
00033             try:
00034                 self._retval = self.__target(*self.__args, **self.__kwargs)
00035             except:
00036                 if sys:
00037                     self._exception = sys.exc_info()
00038 
00039     def return_value(self):
00040         '''Return value from target function.
00041 
00042         This can only be called after the thread has finished, i. e. when
00043         isAlive() is False and did not terminate with an exception.
00044         '''
00045         assert not self.isAlive()
00046         assert not self._exception
00047         return self._retval
00048 
00049     def exc_info(self):
00050         '''Return (type, value, traceback) of the exception caught in run().'''
00051 
00052         return self._exception
00053 
00054     def exc_raise(self):
00055         '''Raise the exception caught in the thread.
00056 
00057         Do nothing if no exception was caught.
00058         '''
00059         if self._exception:
00060             # there is no syntax which both Python 2 and 3 parse, so we need a
00061             # hack using exec() here
00062             # Python 3:
00063             if sys.version > '3':
00064                 raise self._exception[0](self._exception[1]).with_traceback(self._exception[2])
00065             else:
00066                 exec('raise self._exception[0], self._exception[1], self._exception[2]')