retry many times decorator

MRAB python at mrabarnett.plus.com
Thu Jun 28 18:12:40 CEST 2012


On 28/06/2012 16:28, andrea crotti wrote:
> Hi everyone, I'm replacing a perl system that has to work a lot with
> databases and perforce (and a few other things).
>
> This script have to run completely unsupervisioned, so it's important
> that it doesn't just quit at the first attempt waiting for human
> intervent..
>
> They say that the network sometimes has problems so all over the code
> there are things like:
> until ($dbh = DBI->connect('...'))
> {
>      sleep( 5 * 60 );
> )
>
>
> Since I really don't want to do that I tried to do a decorator:
>
> class retry_n_times:
>      def __init__(self, ntimes=3, timeout=3, fatal=True):
>          self.ntimes = ntimes
>          self.timeout = timeout
>          self.fatal = fatal
>
>      def __call__(self, func):
>          def _retry_n_times(*args, **kwargs):
>              attempts = 0
>              while True:
>                  logger.debug("Attempt number %s of %s" % (attempts,
> func.__name__))
>                  ret = func(*args, **kwargs)
>                  if ret:
>                      return ret
>                  else:
>                      sleep(self.timeout)
>
>                  attempts += 1
>                  if attempts == self.ntimes:
>                      logger.error("Giving up the attempts while running
> %s" % func.__name__)
>                      if self.fatal:
>                          exit(100)
>
>          return _retry_n_times
>
> which can be used as
>
> @retry_n_times(ntimes=10)
> def connect():
>      try:
>          conn = mysql_connection()
>      except Exception:
>          return False
>      else:
>          return True
>
>
> So the function to be decorated has to return a boolean..  The problem
> is that I would like to keep the exception message to report a bit
> better what could be the problem, in case the retry fails.
>
> Any idea about how to improve it?
>
Returning a boolean isn't very Pythonic. It would be better, IMHO, if
it could swallow a specified exception (or specified exceptions?)
raised when an attempt failed, up to the maximum permitted number of
attempts. If the final attempt fails, propagate the exception.


More information about the Python-list mailing list