Skip to content

Instantly share code, notes, and snippets.

@MihanixA
Created February 12, 2020 00:01
Python Exponential Retry Decorator
import time
import math
from copy import deepcopy
from typing import List, Type, Union, Callable, Any, Optional
from functools import wraps
def exp_retry(count: int = 5, power: Union[int, float] = 2, ignore_exceptions: List[Type[BaseException]] = None,
raise_on_failure: Optional[Type[BaseException]] = Exception) -> Callable:
ignore_exceptions: list = deepcopy(ignore_exceptions) if ignore_exceptions is not None else list()
def decorator(f: Callable) -> Callable:
retries_so_far: int = 0
@wraps(f)
def wrapper(*args, **kwargs) -> Any:
nonlocal retries_so_far
while retries_so_far < count:
try:
return f(*args, **kwargs)
except Exception as e:
should_ignore = False
for exc in ignore_exceptions:
if isinstance(e, exc):
should_ignore = True
if not should_ignore:
retries_so_far += 1
timeout: float = math.pow(retries_so_far, power)
print(f'\033[93mretrying in {timeout:.2f}s, retries left {count - retries_so_far:,}\033[0m')
time.sleep(timeout)
else:
print(f'\033[91mexception ignored\033[0m')
raise
else:
print('\033[91mretry limit exceeded\033[0m')
if raise_on_failure:
raise raise_on_failure()
return wrapper
return decorator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment