Registry / testing / redo
library3.0.0pypypi✓ verified 24d ago

Redo is a Python library that provides various mechanisms to add seamless retry functionality to any Python callable. It includes plain functions (redo.retry, redo.retry_async), decorators (redo.retriable, redo.retriable_async), and a context manager (redo.retrying). The current version is 3.0.0, released on July 17, 2024. It enables developers to integrate retry logic with customizable backoff strategies, making code more resilient to transient failures.

pip install redo
INSTALL
IMPORT
SIG · REDO
R
redo
testingpythonv3.0.0
Install
1.5s avg
Import
201ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.218s · 17.8MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.5s · import 0.184s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

retry
from redo import retry
For functional usage
retriable
from redo import retriable
For decorator usage
retrying
from redo import retrying
For context manager usage
retry_async
from redo import retry_async
For asynchronous functional usage
retriable_async
from redo import retriable_async
For asynchronous decorator usage

This quickstart demonstrates using the `@retriable` decorator to automatically retry a potentially flaky function. It configures exponential backoff with jitter and specifies which exceptions should trigger a retry. The `attempt_num` argument in `flaky_operation` is illustrative and would typically be handled internally by `redo`'s retry mechanism counting attempts.

import random import time from redo import retriable MAX_ATTEMPTS = 3 @retriable( attempts=MAX_ATTEMPTS, sleeptime=0.1, # initial sleep in seconds max_sleeptime=1.0, # max sleep per retry sleepscale=2, # exponential backoff factor jitter=0.02, # random +/- seconds to add to sleeptime retry_exceptions=(RuntimeError, ConnectionError) # specify exceptions to retry ) def flaky_operation(attempt_num: int): # Simulate a network call or I/O operation that might fail if random.random() < 0.7 and attempt_num < MAX_ATTEMPTS: # 70% chance of failure for initial attempts print(f"Attempt {attempt_num}: Operation failed, retrying...") raise ConnectionError("Failed to connect to service") print(f"Attempt {attempt_num}: Operation successful!") return "Success" if __name__ == "__main__": print("Starting flaky operation...") try: result = flaky_operation(attempt_num=1) print(f"Final result: {result}") except Exception as e: print(f"Operation ultimately failed after multiple retries: {e}")
Debug
Known issues
gotchaBy default, `redo.retriable` and `redo.retry` catch `Exception` if `retry_exceptions` is not specified. This can mask underlying issues that should not be retried, making debugging difficult.
fix
Always explicitly define `retry_exceptions` to a tuple of specific exception types that are expected and can be resolved by retrying, e.g., `retry_exceptions=(ConnectionError, TimeoutError)`.
affects: All versions
gotchaMisconfiguring backoff parameters (`attempts`, `sleeptime`, `max_sleeptime`, `sleepscale`, `jitter`) can lead to excessive delays or a large number of retries, potentially overloading services or causing long wait times.
fix
Carefully test and tune backoff parameters to match the expected retry behavior and system load. Ensure `max_sleeptime` prevents indefinite waits and `attempts` limits overall retry count.
affects: All versions
gotchaIncorrectly mixing synchronous and asynchronous retry mechanisms (e.g., using `redo.retriable` with an `async def` function, or `redo.retriable_async` with a `def` function) will lead to runtime errors or unexpected behavior.
fix
Always use the `_async` variants (`redo.retry_async`, `redo.retriable_async`) for `async def` callables and the non-`_async` variants for synchronous callables.
affects: All versions with async support
Upgrade
Version history
3.0.0latest on PyPI · released Jul 17, 2024
Audit
Dependencies

No dependency data recorded yet.

Agent activity
7 hits · last 30 days
node
6
Resources
redo — pip install redo · libregistry