Backoff-Utils
Backoff-Utils is a Python library that provides functions and decorators for various backoff/retry strategies to Python function and method calls. It offers a consistent syntax and has been tested across a broad range of Python versions, including 2.7, 3.4, 3.5, 3.6, 3.7, and 3.8. The current version is 1.0.1, with recent updates focusing on documentation clarity and dependency management.
Common errors
-
ImportError: No module named 'backoff_utils'
cause The `backoff-utils` package has not been installed in the current Python environment.fixRun `pip install backoff-utils` to install the library. -
TypeError: Can't instantiate abstract class BackoffStrategy with abstract methods time_to_sleep
cause Attempting to instantiate the abstract base class `BackoffStrategy` directly, which lacks a concrete implementation for `time_to_sleep`.fixInstead of `strategy=strategies.BackoffStrategy`, use a concrete strategy like `strategy=strategies.Exponential` or an instance of a concrete strategy like `strategy=strategies.Linear(interval=2)`. -
TypeError: my_failure_handler() takes 1 positional argument but 3 were given
cause A custom `on_failure` callback function was provided to `backoff()` or `@apply_backoff()` with an incorrect signature. It must accept `error`, `message`, and `traceback` arguments.fixModify the `on_failure` function signature to `def my_failure_handler(error, message, traceback): ...`.
Warnings
- gotcha The `BackoffStrategy` class is an abstract base class and cannot be instantiated directly. You must use one of its concrete subclasses (e.g., `strategies.Exponential`, `strategies.Linear`) or create your own custom strategy by subclassing it.
- gotcha When providing custom `on_failure` or `on_success` handlers, their signatures must match specific requirements. An `on_failure` handler must accept three positional arguments: `error`, `message`, and `traceback`. An `on_success` handler must accept a single `result` argument.
- gotcha If `max_tries` or `max_delay` are not explicitly provided, the library will attempt to read default values from the `BACKOFF_DEFAULT_TRIES` and `BACKOFF_DEFAULT_DELAY` environment variables, respectively. If these are also not set, `max_tries` defaults to 3, and `max_delay` defaults to infinite (no maximum).
Install
-
pip install backoff-utils
Imports
- backoff
from backoff_utils import backoff
- apply_backoff
from backoff_utils import apply_backoff
- strategies
from backoff_utils import strategies
Quickstart
import random
import time
from backoff_utils import backoff, apply_backoff, strategies
# Example 1: Using backoff() as a function call
print("\n--- Function Call Example ---")
def unreliable_function(attempt_num):
print(f"Attempting function (call #{attempt_num})...")
if random.random() < 0.7: # 70% chance of failure
raise ConnectionError("Simulated network error")
return f"Success on attempt {attempt_num}!"
try:
result_func = backoff(
unreliable_function,
args=[0], # Placeholder, actual attempt num passed internally
max_tries=5,
max_delay=60,
strategy=strategies.Exponential,
catch_exceptions=(ConnectionError,)
)
print(result_func)
except ConnectionError as e:
print(f"Function failed after multiple retries: {e}")
# Example 2: Using @apply_backoff() as a decorator
print("\n--- Decorator Example ---")
@apply_backoff(
strategy=strategies.Linear(interval=1),
max_tries=4,
catch_exceptions=(IOError,)
)
def another_unreliable_function(data):
print(f"Processing '{data}' (decorated function)...")
if random.random() < 0.5: # 50% chance of failure
raise IOError("Simulated disk write error")
return f"Successfully processed '{data}'"
try:
result_decorator = another_unreliable_function("important data")
print(result_decorator)
except IOError as e:
print(f"Decorated function failed after multiple retries: {e}")