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.

Easy Python 3.9+ Aug 9, 2026 Errors & debugging 15 views 0 copies

Python code

28 lines
Python 3.9+
import 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

stdout
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

  1. Use `time.sleep` with exponential backoff (e.g., `delay * 2 ** attempt`) for more robust retry timing
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Errors & debugging

Related tutorials and quizzes for this topic.