Metadata-Version: 2.4 Name: retrying Version: 1.4.2 Summary: Retrying Author: Alex 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 License-Expression: Apache-2.0 Project-URL: Homepage, https://github.com/groodt/retrying Project-URL: Repository, https://github.com/groodt/retrying Keywords: decorator,decorators,retry,retrying,exception,exponential,backoff Classifier: Intended Audience :: Developers Classifier: Natural Language :: English Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Internet Classifier: Topic :: Utilities Requires-Python: >=3.6 Description-Content-Type: text/markdown License-File: LICENSE.txt License-File: NOTICE.txt Dynamic: license-file # 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.