{"library":"redo","title":"Redo: Utilities to retry Python callables","description":"Redo is a Python library that provides various mechanisms to add seamless retry functionality to any Python callable. It includes plain functions (redo.retry, redo.retry_async), decorators (redo.retriable, redo.retriable_async), and a context manager (redo.retrying). The current version is 3.0.0, released on July 17, 2024. It enables developers to integrate retry logic with customizable backoff strategies, making code more resilient to transient failures.","language":"python","status":"active","last_verified":"Fri May 15","install":{"commands":["pip install redo"],"cli":null},"imports":["from redo import retry","from redo import retriable","from redo import retrying","from redo import retry_async","from redo import retriable_async"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import random\nimport time\nfrom redo import retriable\n\nMAX_ATTEMPTS = 3\n\n@retriable(\n    attempts=MAX_ATTEMPTS,\n    sleeptime=0.1,  # initial sleep in seconds\n    max_sleeptime=1.0, # max sleep per retry\n    sleepscale=2,   # exponential backoff factor\n    jitter=0.02,    # random +/- seconds to add to sleeptime\n    retry_exceptions=(RuntimeError, ConnectionError) # specify exceptions to retry\n)\ndef flaky_operation(attempt_num: int):\n    # Simulate a network call or I/O operation that might fail\n    if random.random() < 0.7 and attempt_num < MAX_ATTEMPTS: # 70% chance of failure for initial attempts\n        print(f\"Attempt {attempt_num}: Operation failed, retrying...\")\n        raise ConnectionError(\"Failed to connect to service\")\n    print(f\"Attempt {attempt_num}: Operation successful!\")\n    return \"Success\"\n\nif __name__ == \"__main__\":\n    print(\"Starting flaky operation...\")\n    try:\n        result = flaky_operation(attempt_num=1)\n        print(f\"Final result: {result}\")\n    except Exception as e:\n        print(f\"Operation ultimately failed after multiple retries: {e}\")","lang":"python","description":"This quickstart demonstrates using the `@retriable` decorator to automatically retry a potentially flaky function. It configures exponential backoff with jitter and specifies which exceptions should trigger a retry. The `attempt_num` argument in `flaky_operation` is illustrative and would typically be handled internally by `redo`'s retry mechanism counting attempts.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-15","installed_version":"3.0.0","pypi_latest":"3.0.0","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":1.6,"avg_import_s":0.2,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.09,"mem_mb":4,"disk_size":"17.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.06,"mem_mb":4,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.16,"mem_mb":5,"disk_size":"19.7M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.6,"import_time_s":0.16,"mem_mb":5,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.37,"mem_mb":8.2,"disk_size":"11.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.33,"mem_mb":8.2,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.37,"mem_mb":8.7,"disk_size":"11.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.32,"mem_mb":8.7,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.08,"mem_mb":3.9,"disk_size":"17.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"redo","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.8,"import_time_s":0.07,"mem_mb":3.9,"disk_size":"18M"}]}}