PYTHON

Implementing a Simple Retry Logic for Unreliable API Calls

Enhance API integration resilience with a Python retry mechanism for transient failures, using exponential backoff to manage external service instability.

import requests
import time
import random

MAX_RETRIES = 3
INITIAL_BACKOFF_SECONDS = 1
API_ENDPOINT = "https://api.example.com/unreliable-service/data" # Replace with your target API
API_KEY = "your_api_key_here" # Securely store this!

def call_api_with_retry(method, url, headers=None, json_data=None, params=None, max_retries=MAX_RETRIES, initial_backoff=INITIAL_BACKOFF_SECONDS):
    """
    Calls an API endpoint with a retry mechanism and exponential backoff.
    Handles transient errors like 5xx status codes, network issues, or timeouts.
    """
    attempt = 0
    while attempt < max_retries:
        attempt += 1
        try:
            print(f"Attempt {attempt}/{max_retries} to call {url}")
            response = requests.request(
                method,
                url,
                headers=headers,
                json=json_data,
                params=params,
                timeout=5 # Set a timeout for the request
            )
            response.raise_for_status() # Raise an exception for HTTP errors (4xx/5xx)

            # If successful, break the loop and return response
            return response.json()

        except requests.exceptions.Timeout:
            print(f"Request timed out on attempt {attempt}.")
            # Retry on timeout
        except requests.exceptions.ConnectionError:
            print(f"Connection error on attempt {attempt}.")
            # Retry on connection error
        except requests.exceptions.HTTPError as e:
            # Retry only on specific server errors (e.g., 5xx status codes)
            if 500 <= e.response.status_code < 600:
                print(f"Server error ({e.response.status_code}) on attempt {attempt}. Retrying...")
            else:
                # For client errors (4xx) or other unretriable errors, re-raise
                print(f"Unretriable HTTP error ({e.response.status_code}) on attempt {attempt}.")
                raise # Re-raise the exception for non-retriable errors
        except requests.exceptions.RequestException as e:
            print(f"An unexpected request error occurred on attempt {attempt}: {e}")

        # If it's the last attempt, don't sleep, just fail
        if attempt == max_retries:
            print(f"Max retries ({max_retries}) reached. Failing request.")
            break

        # Calculate exponential backoff with jitter
        backoff_time = initial_backoff * (2 ** (attempt - 1)) + random.uniform(0, 0.5)
        print(f"Waiting {backoff_time:.2f} seconds before next retry...")
        time.sleep(backoff_time)

    raise requests.exceptions.RequestException(f"Failed to call API after {max_retries} attempts.")


if __name__ == "__main__":
    # Example usage:
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json"
    }

    try:
        # Simulate a GET request
        print("
Attempting GET request...")
        result = call_api_with_retry("GET", API_ENDPOINT, headers=headers, params={"limit": 1})
        print("GET request successful:", result)

        # Simulate a POST request (if the API supports it)
        # print("
Attempting POST request...")
        # post_data = {"item": "new_resource"}
        # result = call_api_with_retry("POST", API_ENDPOINT, headers=headers, json_data=post_data)
        # print("POST request successful:", result)

    except requests.exceptions.RequestException as e:
        print(f"Application failed after retries: {e}")
    except Exception as e:
        print(f"An unexpected application error occurred: {e}")
How it works: This Python snippet implements a robust retry mechanism for API calls, designed to handle transient network issues, timeouts, and server-side errors (5xx). It uses an exponential backoff strategy with added jitter (randomness) to prevent thundering herd problems, ensuring that the application can gracefully recover from temporary external API unavailabilities without overwhelming the service. This significantly improves the reliability of API integrations.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs