148 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 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.
 |