Skip to main content

ReAttempt

ReAttempt is a python decorator to retry a function when exceptions are raised.

Demonstration:

from reattempt import reattempt

@reattempt(max_retries=5, min_time=0.1, max_time=2)
def simulate_network_failure():
    raise Exception("Connection timeout")

if __name__ == "__main__":
    simulate_network_failure()

------------------------------------------------------- live log call -------------------------------------------------------
WARNING  root:__init__.py:167 [RETRY] Attempt 1/5 failed, retrying in 0.17 seconds...
WARNING  root:__init__.py:167 [RETRY] Attempt 2/5 failed, retrying in 0.19 seconds...
WARNING  root:__init__.py:167 [RETRY] Attempt 3/5 failed, retrying in 0.19 seconds...
WARNING  root:__init__.py:167 [RETRY] Attempt 4/5 failed, retrying in 0.19 seconds...
WARNING  root:__init__.py:163 [RETRY] Attempt 5/5 failed, stopping
ERROR    root:__init__.py:177 [RETRY] Max retries reached

Table of Contents

Description

ReAttempt is a Python library that provides a decorator to automatically retry a function when exceptions are raised. It uses an exponential backoff strategy to wait between retries, ensuring that the function has multiple chances to succeed before ultimately failing.

Installation

# Install the dependency
pip install reattempt
uv add reattempt
poetry add reattempt

Usage

from reattempt import reattempt
import asyncio
import random

# List of flowers for our examples
flowers = ["Rose", "Tulip", "Sunflower", "Daisy", "Lily"]

# Synchronous function example
@reattempt
def plant_flower():
    flower = random.choice(flowers)
    print(f"Attempting to plant a {flower}")
    if random.random() < 0.8:  # 80% chance of failure
        raise Exception(f"The {flower} didn't take root")
    return f"{flower} planted successfully"

# Synchronous generator example
@reattempt
def grow_flowers():
    for _ in range(3):
        flower = random.choice(flowers)
        print(f"Growing {flower}")
        yield flower
    if random.random() < 0.5:  # 50% chance of failure at the end
        raise Exception("The garden needs more fertilizer")

# Asynchronous function example
@reattempt
async def water_flower():
    flower = random.choice(flowers)
    print(f"Watering the {flower}")
    await asyncio.sleep(0.1)  # Simulating watering time
    if random.random() < 0.6:  # 60% chance of failure
        raise Exception(f"The {flower} needs more water")
    return f"{flower} is well-watered"

# Asynchronous generator function example
@reattempt
async def harvest_flowers():
    for _ in range(3):
        flower = random.choice(flowers)
        print(f"Harvesting {flower}")
        yield flower
        await asyncio.sleep(0.1)  # Time between harvests
    if random.random() < 0.4:  # 40% chance of failure at the end
        raise Exception("The garden needs more care")

async def tend_garden():
    # Plant a flower (sync function)
    try:
        result = plant_flower()
        print(result)
    except Exception as e:
        print(f"Planting error: {e}")

    # Grow flowers (sync generator)
    try:
        for flower in grow_flowers():
            print(f"Grown: {flower}")
    except Exception as e:
        print(f"Growing error: {e}")

    # Water a flower (async function)
    try:
        result = await water_flower()
        print(result)
    except Exception as e:
        print(f"Watering error: {e}")

    # Harvest flowers (async generator function)
    try:
        async for flower in harvest_flowers():
            print(f"Harvested: {flower}")
    except Exception as e:
        print(f"Harvesting error: {e}")

if __name__ == "__main__":
    asyncio.run(tend_garden())

License

ReAttempt is released under the MIT License. See the LICENSE file for more details.

Contact

For questions, suggestions, or issues related to ReAttempt, please open an issue on the GitHub repository.

Metadata

Release files for reattempt 1.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for reattempt 1.1.4
File Size Uploaded
reattempt-1.1.4.tar.gz 49.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for reattempt 1.1.4
File Interpreter ABI Platform
reattempt-1.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 54.6 kB

Release files / reattempt-1.1.4.tar.gz

Download URL reattempt-1.1.4.tar.gz
Size 49.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c02ed738dacbacbb757bc97c778dc17aa098dc08bed9f97405285e8a2c042d91
BLAKE2b-256 checksum
How to use checksums
896c9f166587c440ca6ee7d34b0d0dc9a6a548b9e6687ffd3857145edbe25fd2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / reattempt-1.1.4-py3-none-any.whl

Download URL reattempt-1.1.4-py3-none-any.whl
Size 5.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4791253f69c4b5994c5b3fba7e47dd081159a3ae80126da16920a1788a8c9074
BLAKE2b-256 checksum
How to use checksums
9dbfcd854626debfb0b891625afb10411929fc9431c618e77bbef78749f8c1cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Release history Release notifications | RSS feed

This release

1.1.4 This release

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.10

2 release files

1.0.9

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page