A python exception retry decorator

We usually call some API functions which may throw exception because of unexpected condition. These unexpected condition include but not limited to service too busy, network packet loss, etc. and it would be OK if we retry again.

So we need a decorator for this purpose, then we can easily make the API calls more stable.

def retry(tries, delay=1, backoff=2):
    """
    A retry decorator with exponential backoff,
    Retries a function or method if Exception occurred

    Args:
        tries: number of times to retry, set to 0 to disable retry
        delay: initial delay in seconds(can be float, eg 0.01 as 10ms),
            if the first run failed, it would sleep 'delay' second and try again
        backoff: must be greater than 1, 
            further failure would sleep delay *= backoff second 
    """
    import time
    import math

    if backoff <= 1:
        raise ValueError("backoff must be greater than 1")

    tries = math.floor(tries)
    if tries < 0:
        raise ValueError("tries must be 0 or greater")

    if delay <= 0:
        raise ValueError("delay must be greater than 0")

    def decorator(func):
        def wrapper(*args, **kwargs):
            _tries, _delay = tries, delay
            _tries += 1 #ensure we call func at least once
            while _tries > 0:
                try:
                    ret = func(*args, **kwargs)
                    return ret
                except Exception as e:
                    _tries -= 1
                    #retried enough and still fail? raise orignal exception
                    if _tries == 0: raise
                    time.sleep(_delay)
                    #wait longer after each failure
                    _delay *= backoff
        return wrapper

    return decorator

Usage example:

@retry(3, delay=0.1)
def give_me_five():
    n = random.randint(1, 10)
    print "got #: %s" % n
    if n != 5:
        raise ValueError("Please give me five")
    return n

n = give_me_five()
print "main got:%s " % n
This entry was posted in Programming, Python and tagged , , , . Bookmark the permalink.

Leave a Reply