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())