Package: tryagain
tryagainA lightweight and pythonic retry helper.tryagainaims to simplify working with unstable functions. Whether
you have networking code that sometimes raises timeout exceptions or you
are controlling devices which only seem to listen on the second try -tryagainmakes it easier to repeat the call.tryagainoffers you hooks to clean up after a failed attempt or to
prepare for the next call. You can set a waittime between retries or
specify your own waittime function to realize exponential waittimes etc.tryagainis lightweight, fully tested, MIT licensed and comes as a single
python file with no dependencies. It supports Python 2.6+ and 3.2+.To install, runpip install tryagain.Basic syntaxUsing the tryagain functioncall:importtryagaindefunstable_function():# Attention: This function sometimes fails!...result=tryagain.call(unstable_function,max_attempts=None,exceptions=Exception,wait=0.0,cleanup_hook=None,pre_retry_hook=None)Using the tryagain decoratorretries:fromtryagainimportretries@retries(max_attempts=3)defunstable_funcation(arg1,arg2):# Attention: This function sometimes fails!...result=unstable_function('foo',arg2='bar')Parametersfunc: The unstable function to callmax_attemps: Any integer number to limit the maximum number of
attempts. Set to None for unlimited retries. (Default = None)exceptions: An iterable of exceptions that should result in a
retry. (Default =Exception)wait: Can be an integer or float value (to specify a waittime in seconds) or a custom function (see Waittime documentation) (Default = 0.0)cleanup_hook: Can be set to a callable and will be called after
an exception is raised from callingfunc. (Default = None)pre_retry_hook: Can be set to any callable that will be called
beforefuncis called. (Default = None)Resulttryagain.callwill return whatever the unstable function would
return.tryagain.call(and the decoratortryagain.retries) reraises
any exception which is:not in the givenexceptionsraised in thepre_retry_hookor incleanup_hookraised in the last attempt at calling the unstable function.QuickstartRetry calling an unstable functionimporttryagaindefunstable():...# retry calling 'unstable' until it returns without raising an exceptionresult=tryagain.call(unstable)# limit to maximum 5 attemptsresult=tryagain.call(unstable,max_attempts=5)# only retry after specific exceptionsresult=tryagain.call(unstable,exceptions=(ValueError,TypeError))WaittimesThe tryagain library allows fixed wait values as well as custom waittime
functions.# wait one second before trying againtryagain.call(unstable,wait=1.0)# waittime rises linearly (n is the number of attempts)# (will wait 1s, 2s, 3s, ...)tryagain.call(unstable,wait=lambdan:n)# waittime rises exponentially with each attempt# (will wait 2s, 4s, 8s, ...)tryagain.call(unstable,wait=lambdan:2**n)# exponentially rising waittime with maximum# (will wait 2s, 4s, 5s, 5s, ..., 5s)tryagain.call(unstable,wait=lambdan:min(n**2,5))# no waiting time before second attempt, 1.0s afterwardsdefno_first_wait(attempt):ifattempt==2:return0else:return1.0tryagain.call(unstable,wait=no_first_wait)Retry calling a function with parametersThetryagain.call-function only supports a function reference as thefuncparameter. To pass arguments to the unstable function you have to use
one of the following idioms:# using a lambdatryagain.call(lambda:unstable('message',some_arg=True),wait=1.0)# using a partialfromfunctoolsimportpartialtryagain.call(partial(unstable,'message',some_arg=True),wait=1.0)# using a separate functiondefcall_unstable_function():msg='message'returnunstable(msg,some_arg=True)tryagain.call(call_unstable_function,wait=1.0)But it is much nicer to wrap your unstable function in the@retriesdecorator.
This way you can call your unstable function with parameters easily:Function decoratorInstead of using thetryagain.callfunction, you can use theretriesdecorator.fromtryagainimportretries@retries(max_attempts=3,exceptions=(TypeError,ValueError))defunstable(arg1,arg2):# your unstable function hereresult=unstable('foo',arg2='bar')The decorator takes the same arguments as thecall-function
except thefuncparameter.HooksThe tryagain library features two hooks that can be used,cleanup_hookandpre_retry_hook.defunstable():print('Calling unstable function')print('Exception!')raiseExceptiontryagain.call(unstable,max_attempts=2,wait=lambdan:print('waiting'),cleanup_hook=lambda:print('cleaning up'),pre_retry_hook=lambda:print('do preparations'))'Calling unstable function''Exception!''cleaning up''waiting''do preparations''Calling unstable function''Exception!''cleaning up'Error:Exceptionraised...