Retry a flaky call with exponential backoff

A decorator that retries a function on chosen exceptions, waiting longer after each failure.

python intermediate #retry#decorators#network
在游乐场中打开
python-retry-backoff.py
import functools
import random
import time


def retry(times=3, base_delay=0.5, exceptions=(Exception,)):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(1, times + 1):
                try:
                    return func(*args, **kwargs)
                except exceptions as exc:
                    if attempt == times:
                        raise
                    delay = base_delay * 2 ** (attempt - 1) + random.uniform(0, 0.1)
                    print(f"attempt {attempt} failed ({exc}); retrying in {delay:.2f}s")
                    time.sleep(delay)
        return wrapper
    return decorator


calls = {"n": 0}

@retry(times=4, base_delay=0.1, exceptions=(ConnectionError,))
def fetch():
    calls["n"] += 1
    if calls["n"] < 3:
        raise ConnectionError("server busy")
    return "ok"

print(fetch())