Create a retry decorator with max attempts in Python
A decorator that retries a function up to a specified number of times when it raises an exception, with an optional delay between attempts.
Python code
31 linesimport functools
import time
def retry(max_attempts, delay=0.1):
"""Retry a function up to max_attempts times on exception."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"Attempt {attempt} failed: {e}. Retrying...")
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=3, delay=0.05)
def flaky_operation():
import random
if random.random() < 0.6:
raise ValueError("Transient failure")
return "Success"
if __name__ == "__main__":
print(flaky_operation())
Output
Attempt 1 failed: Transient failure. Retrying...
Success
How it works
The retry decorator wraps a function so that each call enters a loop up to max_attempts times. On each exception, it checks if it's the last attempt and either raises the original exception or prints a message and sleeps. functools.wraps preserves the original function's metadata. This pattern is useful for handling transient failures in network calls or external services.
Common mistakes
- Catching `Exception` may hide programmer errors like `KeyboardInterrupt` or `SystemExit`.
- Forgetting to re-raise on the final attempt, making the function return `None` silently.
- Using a fixed delay without backoff, causing repeated immediate retries.
Variations
- Add exponential backoff with `time.sleep(delay * (2 ** (attempt - 1)))`.
- Use `retry` from third-party libraries like `tenacity` for more control.
Real-world use cases
- Retrying a network request to an API that occasionally fails with a 503 status.
- Handling transient database connection errors when running a batch job.
- Retrying a file upload to cloud storage when the connection drops mid-transfer.
Sponsored
More from Functions & basics
- Add Type Hints to Function Parameters and Return in Python easy
- Benchmark list append vs comprehension in Python easy
- Build a Context Manager in Python with contextlib.contextmanager easy
- Build a Progress Callback Function for Loops in Python easy
- Cache expensive function with lru_cache in Python easy
- Calculate Time Difference Across Time Zones in Python easy
Keep learning
Related tutorials and quizzes for this topic.