Retry an Operation on ConnectionError in Python
Retries an unreliable operation a fixed number of times when it raises a transient ConnectionError, with a small delay between attempts.
Python code
28 linesimport time
import random
def unreliable_operation():
"""Simulates an operation that throws ConnectionError occasionally."""
if random.random() < 0.6:
raise ConnectionError("Transient network failure")
return "Operation succeeded"
def retry_operation(attempts=4, delay=0.2):
"""Retries the operation on ConnectionError with a small delay."""
for attempt in range(1, attempts + 1):
try:
result = unreliable_operation()
print(f"Attempt {attempt}: {result}")
return result
except ConnectionError as exc:
print(f"Attempt {attempt}: {exc} — retrying...")
time.sleep(delay)
print(f"Failed after {attempts} attempts")
return None
if __name__ == "__main__":
random.seed(1) # deterministic output for demonstration
retry_operation()
Output
Attempt 1: Transient network failure — retrying...
Attempt 2: Transient network failure — retrying...
Attempt 3: Operation succeeded
How it works
The retry_operation function wraps each call in a try/except block that catches ConnectionError. On failure, it sleeps for a short delay before attempting again, up to the configured total. The loop increments the attempt counter so the function knows how many retries remain. When an attempt succeeds, the result is returned immediately, breaking out of the loop. If all attempts fail, the function reports failure and returns None.
Common mistakes
- Catching the wrong exception — use `ConnectionError`, not generic `Exception`, to avoid masking real bugs
- Forgetting to add a delay between retries, causing a tight loop and hammering the network
- Not setting a maximum attempt count, allowing infinite retries in production
- Ignoring the return value from a failed final attempt instead of checking for `None`
Variations
- Use `time.sleep` with exponential backoff (e.g., `delay * 2 ** attempt`) for more robust retry timing
- Add a `max_delay` cap and jitter (randomization) to avoid thundering herd problems
Real-world use cases
- Retrying a database connection when a pool briefly times out during a spike.
- Re-calling a third-party REST API that intermittently returns 500 errors or drops connections.
- Handling temporary network blips when downloading large files or syncing data to a remote service.
Sponsored
More from Errors & debugging
- Catch RecursionError and Fail Gracefully in Python easy
- Catch ValueError and print friendly message in Python easy
- Collect Multiple Validation Errors in Python Before Raising medium
- Handle ValueError and ZeroDivisionError in Python with try except easy
- How to Add a Correlation ID to Logging Records in Python medium
- How to Assert Preconditions with Descriptive Messages in Python easy
Keep learning
Related tutorials and quizzes for this topic.