retrying


Nameretrying JSON
Version 1.4.2 PyPI version JSON
download
home_pageNone
SummaryRetrying
upload_time2025-08-03 03:35:25
maintainerNone
docs_urlNone
authorAlex Kuang, Anthony McClosky, Cyrus Durgin, Daniel Nephin, Dougal Matthews, Greg Roodt, Haïkel Guémar, Hugo Klepsch, J Derek Wilson, James Page, Jason Dunkelberger, Job Evers, Jonathan Herriott, Josh Marshall, Joshua Harlow, Justin Turner Arthur, Maxym Shalenyi, Monty Taylor, Pierre-Yves Chibon, Ray Holder, Rees Dooley, Saul Shanabrook, Simon Dollé, Simeon Visser, Thomas Goirand
requires_python>=3.6
licenseNone
keywords decorator decorators retry retrying exception exponential backoff
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Retrying

Retrying is an Apache 2.0 licensed general-purpose retrying library, written in
Python, to simplify the task of adding retry behavior to just about anything.

The simplest use case is retrying a flaky function whenever an Exception occurs
until a value is returned.

```python
import random
from retrying import retry

@retry
def do_something_unreliable():
    if random.randint(0, 10) > 1:
        raise IOError("Broken sauce, everything is hosed!!!111one")
    else:
        return "Awesome sauce!"

print(do_something_unreliable())
```

## Features

- Generic Decorator API
- Specify stop condition (i.e. limit by number of attempts)
- Specify wait condition (i.e. exponential backoff sleeping between attempts)
- Customize retrying on Exceptions
- Customize retrying on expected returned result

## Examples

As you saw above, the default behavior is to retry forever without waiting.

```python
@retry
def never_give_up_never_surrender():
    print("Retry forever ignoring Exceptions, don't wait between retries")
```

Let's be a little less persistent and set some boundaries, such as the number of attempts before giving up.

```python
@retry(stop_max_attempt_number=7)
def stop_after_7_attempts():
    print("Stopping after 7 attempts")
```

We don't have all day, so let's set a boundary for how long we should be retrying stuff.

```python
@retry(stop_max_delay=10000)
def stop_after_10_s():
    print("Stopping after 10 seconds")
```

Most things don't like to be polled as fast as possible, so let's just wait 2 seconds between retries.

```python
@retry(wait_fixed=2000)
def wait_2_s():
    print("Wait 2 second between retries")
```

Some things perform best with a bit of randomness injected.

```python
@retry(wait_random_min=1000, wait_random_max=2000)
def wait_random_1_to_2_s():
    print("Randomly wait 1 to 2 seconds between retries")
```

Then again, it's hard to beat exponential backoff when retrying distributed services and other remote endpoints.

```python
@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
def wait_exponential_1000():
    print("Wait 2^x * 1000 milliseconds between each retry, up to 10 seconds, then 10 seconds afterwards")
```

We have a few options for dealing with retries that raise specific or general exceptions, as in the cases here.

```python
def retry_if_io_error(exception):
    """Return True if we should retry (in this case when it's an IOError), False otherwise"""
    return isinstance(exception, IOError)

@retry(retry_on_exception=retry_if_io_error)
def might_io_error():
    print("Retry forever with no wait if an IOError occurs, raise any other errors")

@retry(retry_on_exception=retry_if_io_error, wrap_exception=True)
def only_raise_retry_error_when_not_io_error():
    print("Retry forever with no wait if an IOError occurs, raise any other errors wrapped in RetryError")
```

We can also use the result of the function to alter the behavior of retrying.

```python
def retry_if_result_none(result):
    """Return True if we should retry (in this case when result is None), False otherwise"""
    return result is None

@retry(retry_on_result=retry_if_result_none)
def might_return_none():
    print("Retry forever ignoring Exceptions with no wait if return value is None")
```

Any combination of stop, wait, etc. is also supported to give you the freedom to mix and match.

## Contribute

1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.
2. Fork [the repository](http://github.com/groodt/retrying) on GitHub to start making your changes to the **master** branch (or branch off of it).
3. Write a test which shows that the bug was fixed or that the feature works as expected.
4. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to the authors list in pyproject.toml.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "retrying",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "decorator, decorators, retry, retrying, exception, exponential, backoff",
    "author": "Alex Kuang, Anthony McClosky, Cyrus Durgin, Daniel Nephin, Dougal Matthews, Greg Roodt, Ha\u00efkel Gu\u00e9mar, Hugo Klepsch, J Derek Wilson, James Page, Jason Dunkelberger, Job Evers, Jonathan Herriott, Josh Marshall, Joshua Harlow, Justin Turner Arthur, Maxym Shalenyi, Monty Taylor, Pierre-Yves Chibon, Ray Holder, Rees Dooley, Saul Shanabrook, Simon Doll\u00e9, Simeon Visser, Thomas Goirand",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/c8/5a/b17e1e257d3e6f2e7758930e1256832c9ddd576f8631781e6a072914befa/retrying-1.4.2.tar.gz",
    "platform": null,
    "description": "# Retrying\n\nRetrying is an Apache 2.0 licensed general-purpose retrying library, written in\nPython, to simplify the task of adding retry behavior to just about anything.\n\nThe simplest use case is retrying a flaky function whenever an Exception occurs\nuntil a value is returned.\n\n```python\nimport random\nfrom retrying import retry\n\n@retry\ndef do_something_unreliable():\n    if random.randint(0, 10) > 1:\n        raise IOError(\"Broken sauce, everything is hosed!!!111one\")\n    else:\n        return \"Awesome sauce!\"\n\nprint(do_something_unreliable())\n```\n\n## Features\n\n- Generic Decorator API\n- Specify stop condition (i.e. limit by number of attempts)\n- Specify wait condition (i.e. exponential backoff sleeping between attempts)\n- Customize retrying on Exceptions\n- Customize retrying on expected returned result\n\n## Examples\n\nAs you saw above, the default behavior is to retry forever without waiting.\n\n```python\n@retry\ndef never_give_up_never_surrender():\n    print(\"Retry forever ignoring Exceptions, don't wait between retries\")\n```\n\nLet's be a little less persistent and set some boundaries, such as the number of attempts before giving up.\n\n```python\n@retry(stop_max_attempt_number=7)\ndef stop_after_7_attempts():\n    print(\"Stopping after 7 attempts\")\n```\n\nWe don't have all day, so let's set a boundary for how long we should be retrying stuff.\n\n```python\n@retry(stop_max_delay=10000)\ndef stop_after_10_s():\n    print(\"Stopping after 10 seconds\")\n```\n\nMost things don't like to be polled as fast as possible, so let's just wait 2 seconds between retries.\n\n```python\n@retry(wait_fixed=2000)\ndef wait_2_s():\n    print(\"Wait 2 second between retries\")\n```\n\nSome things perform best with a bit of randomness injected.\n\n```python\n@retry(wait_random_min=1000, wait_random_max=2000)\ndef wait_random_1_to_2_s():\n    print(\"Randomly wait 1 to 2 seconds between retries\")\n```\n\nThen again, it's hard to beat exponential backoff when retrying distributed services and other remote endpoints.\n\n```python\n@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)\ndef wait_exponential_1000():\n    print(\"Wait 2^x * 1000 milliseconds between each retry, up to 10 seconds, then 10 seconds afterwards\")\n```\n\nWe have a few options for dealing with retries that raise specific or general exceptions, as in the cases here.\n\n```python\ndef retry_if_io_error(exception):\n    \"\"\"Return True if we should retry (in this case when it's an IOError), False otherwise\"\"\"\n    return isinstance(exception, IOError)\n\n@retry(retry_on_exception=retry_if_io_error)\ndef might_io_error():\n    print(\"Retry forever with no wait if an IOError occurs, raise any other errors\")\n\n@retry(retry_on_exception=retry_if_io_error, wrap_exception=True)\ndef only_raise_retry_error_when_not_io_error():\n    print(\"Retry forever with no wait if an IOError occurs, raise any other errors wrapped in RetryError\")\n```\n\nWe can also use the result of the function to alter the behavior of retrying.\n\n```python\ndef retry_if_result_none(result):\n    \"\"\"Return True if we should retry (in this case when result is None), False otherwise\"\"\"\n    return result is None\n\n@retry(retry_on_result=retry_if_result_none)\ndef might_return_none():\n    print(\"Retry forever ignoring Exceptions with no wait if return value is None\")\n```\n\nAny combination of stop, wait, etc. is also supported to give you the freedom to mix and match.\n\n## Contribute\n\n1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.\n2. Fork [the repository](http://github.com/groodt/retrying) on GitHub to start making your changes to the **master** branch (or branch off of it).\n3. Write a test which shows that the bug was fixed or that the feature works as expected.\n4. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to the authors list in pyproject.toml.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Retrying",
    "version": "1.4.2",
    "project_urls": {
        "Homepage": "https://github.com/groodt/retrying",
        "Repository": "https://github.com/groodt/retrying"
    },
    "split_keywords": [
        "decorator",
        " decorators",
        " retry",
        " retrying",
        " exception",
        " exponential",
        " backoff"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "67f36cd296376653270ac1b423bb30bd70942d9916b6978c6f40472d6ac038e7",
                "md5": "e698656f9d2b65563d50b3c6c9f51546",
                "sha256": "bbc004aeb542a74f3569aeddf42a2516efefcdaff90df0eb38fbfbf19f179f59"
            },
            "downloads": -1,
            "filename": "retrying-1.4.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e698656f9d2b65563d50b3c6c9f51546",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 10859,
            "upload_time": "2025-08-03T03:35:23",
            "upload_time_iso_8601": "2025-08-03T03:35:23.829851Z",
            "url": "https://files.pythonhosted.org/packages/67/f3/6cd296376653270ac1b423bb30bd70942d9916b6978c6f40472d6ac038e7/retrying-1.4.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c85ab17e1e257d3e6f2e7758930e1256832c9ddd576f8631781e6a072914befa",
                "md5": "f21de7ff40577f72d9a08dcc1604d2be",
                "sha256": "d102e75d53d8d30b88562d45361d6c6c934da06fab31bd81c0420acb97a8ba39"
            },
            "downloads": -1,
            "filename": "retrying-1.4.2.tar.gz",
            "has_sig": false,
            "md5_digest": "f21de7ff40577f72d9a08dcc1604d2be",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 11411,
            "upload_time": "2025-08-03T03:35:25",
            "upload_time_iso_8601": "2025-08-03T03:35:25.189544Z",
            "url": "https://files.pythonhosted.org/packages/c8/5a/b17e1e257d3e6f2e7758930e1256832c9ddd576f8631781e6a072914befa/retrying-1.4.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-03 03:35:25",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "groodt",
    "github_project": "retrying",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "retrying"
}
        
Elapsed time: 1.86157s