Guide Python Intermediate

Python Retry and Logging Lab

Practice bounded retries with deterministic failures, backoff, and testable logging.

2 min read

Prerequisites

Know functions, exceptions, and logging from the production scripting bridge. This simulation uses only Python and makes no network calls.

Sample input and task

A fake service raises ConnectionError twice, then returns ok. Allow four total attempts, wait 0.1 then 0.2 seconds between the first three attempts, and log each failure. Propagate unrelated errors immediately.

Expected output

Warnings indicate attempts 1 and 2 failed, then stdout prints ok. No sleep follows success or the last failure. Four total attempts means one original call and at most three retries.

HintPass the operation and sleep function as arguments. Catch only the simulated transient failure and re-raise when the attempt budget is exhausted.
Show solution
import logging
import time


def run_with_retry(operation, max_attempts=4, base_delay=0.1, sleep=time.sleep):
    if max_attempts < 1 or base_delay < 0:
        raise ValueError("Invalid retry configuration")
    for attempt in range(1, max_attempts + 1):
        try:
            return operation()
        except ConnectionError:
            if attempt == max_attempts:
                logging.error("attempt=%d exhausted=true", attempt)
                raise
            delay = min(base_delay * 2 ** (attempt - 1), 5.0)
            logging.warning("attempt=%d retry_in=%.2f", attempt, delay)
            sleep(delay)


def main():
    logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
    outcomes = iter([ConnectionError("temporary"), ConnectionError("temporary"), "ok"])

    def fake_call():
        result = next(outcomes)
        if isinstance(result, Exception):
            raise result
        return result

    print(run_with_retry(fake_call))


if __name__ == "__main__":
    main()

Check your work

Replace sleep with delays.append, where delays = [], to test without waiting.

OperationExpected result
Immediate successOne call; no sleeps.
Two failures then successThree calls; delays [0.1, 0.2].
Always ConnectionErrorFour calls; three sleeps; exception propagates.
ValueErrorOne call; no sleeps; exception propagates.
Zero attempt budgetConfiguration error before any call.

Challenge and production connection

Add bounded jitter and test delay ranges instead of exact values. For a real service, use the client’s exception types and timeouts. Retrying writes requires an idempotency strategy.

For boto3, use SDK retries instead of wrapping them in this simulation: nested policies multiply attempts. The sample logs key/value text; extend it to JSON if your log collector requires JSON events.

Continue to request pacing.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form