Expand FunctionTimedOut exception to have attributes of the timeout, function that failed, args and kwargs. Also add a standard getMsg function for generating consistant message, and add a retry function to retry the function again with either same timeout, different timeout, or no timeout.

This commit is contained in:
Tim Savannah 2017-05-20 16:04:39 -04:00
parent c3a114e1df
commit 5b93fe5d7c
3 changed files with 64 additions and 2 deletions

View File

@ -81,7 +81,7 @@ def func_timeout(timeout, func, args=(), kwargs=None):
stopException = FunctionTimedOut
thread._stopThread(stopException)
thread.join(.1)
raise FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout))
raise FunctionTimedOut('', timeout, func, args, kwargs)
if exception:
raise exception[0]

View File

@ -5,9 +5,64 @@
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
__all__ = ('FunctionTimedOut', 'RETRY_SAME_TIMEOUT')
RETRY_SAME_TIMEOUT = '__rst'
class FunctionTimedOut(BaseException):
'''
FunctionTimedOut - Exception raised when a function times out
@property timedOutAfter - Number of seconds before timeout was triggered
@property timedOutFunction - Function called which timed out
@property timedOutArgs - Ordered args to function
@property timedOutKwargs - Keyword args to function
@method retry - R
'''
pass
def __init__(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None):
self.timedOutAfter = timedOutAfter
self.timedOutFunction = timedOutFunction
self.timedOutArgs = timedOutArgs
self.timedOutKwargs = timedOutKwargs
if not msg:
msg = self.getMsg()
BaseException.__init__(self, msg)
def getMsg(self):
'''
getMsg - Generate a default message based on parameters to FunctionTimedOut exception'
@return <str> - Message
'''
return 'Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(self.timedOutFunction.__name__, repr(self.timedOutArgs), repr(self.timedOutKwargs), self.timedOutAfter)
def retry(self, timeout=RETRY_SAME_TIMEOUT):
'''
retry - Retry the timed-out function with same arguments.
@param timeout <float/RETRY_SAME_TIMEOUT/None> Default RETRY_SAME_TIMEOUT
If RETRY_SAME_TIMEOUT : Will retry the function same args, sane timeout
If a float/int : Will retry the function same args with provided timeout
If None : Will retry function same args no timeout
@return - Returnval from function
'''
if timeout is None:
return self.timedOutFunction(*(self.timedOutArgs), **self.timedOutKwargs)
from .dafunc import func_timeout
if timeout == RETRY_SAME_TIMEOUT:
timeout = self.timedOutAfter
return func_timeout(timeout, self.timedOutFunction, args=self.timedOutArgs, kwargs=self.timedOutKwargs)

View File

@ -15,8 +15,15 @@ if __name__ == '__main__':
print ( "\tGot Return: %s\n" %(str(func_timeout(4, doit, args=(6,))),) )
print ( "\nShould time out (exception):" )
myException = None
try:
print ("\tGot Return: %s\n" %(str(func_timeout(1, doit, kwargs={'howmany' : 16})),))
except FunctionTimedOut as e:
sys.stderr.write('\tGot Exception: %s\n' %(str(e),))
myException = e
pass
if myException is not None:
print ( "\nGot: %s\n" %( str(myException.retry(2.5)), ) )
else:
sys.stderr.write('Did not get exception before?\n')