Package: riprova
riprova(meaningretryin Italian) is a small, general-purpose and versatilePythonlibrary
that provides retry mechanisms with multiple backoff strategies for any sort of failed operations.It’s domain agnostic, highly customizable, extensible and provides a minimal API that’s easy to instrument in any code base via decorators, context managers or raw API consumption.For a brief introduction about backoff mechanisms for potential failed operations,read this article.FeaturesRetry decorator for simple and idiomatic consumption.Simple Pythonic programmatic interface.Maximum retry timeout support.Supports errorwhitelistingandblacklisting.Supports customerror evaluationretry logic (useful to retry only in specific cases).Automatically retry operations on raised exceptions.Supportsasynchronous coroutineswith bothasync/awaitandyield fromsyntax.Configurable maximum number of retry attempts.Highly configurable supporting max retries, timeouts or retry notifier callback.Built-in backoff strategies: constant,fibonacciandexponentialbackoffs.Supports sync/async context managers.Pluggable custom backoff strategies.Lightweight library with almost zero embedding cost.Works with Python +2.6, 3.0+ and PyPy.Backoff strategiesList of built-in backoff strategies.Constant backoffFibonacci backoffExponential backoffYou can also implement your own one easily.
SeeConstantBackofffor an implementation reference.InstallationUsingpippackage manager (requires pip 1.9+. Upgrade it running:pip install-Upip):pipinstall-UriprovaOr install the latest sources from Github:pipinstall-egit+git://github.com/h2non/riprova.git#egg=riprovaAPIriprova.retryriprova.Retrierriprova.AsyncRetrierriprova.Backoffriprova.ConstantBackoffriprova.FibonacciBackoffriprova.ExponentialBackoffriprova.ErrorWhitelistriprova.ErrorBlacklistriprova.add_whitelist_errorriprova.RetryErrorriprova.RetryTimeoutErrorriprova.MaxRetriesExceededriprova.NotRetriableErrorExamplesYou can see more featured examples from thedocumentationsite.Basic usage examples:importriprova@riprova.retrydeftask():"""Retry operation if it fails with constant backoff (default)"""@riprova.retry(backoff=riprova.ConstantBackoff(retries=5))deftask():"""Retry operation if it fails with custom max number of retry attempts"""@riprova.retry(backoff=riprova.ExponentialBackOff(factor=0.5))deftask():"""Retry operation if it fails using exponential backoff"""@riprova.retry(timeout=10)deftask():"""Raises a TimeoutError if the retry loop exceeds from 10 seconds"""defon_retry(err,next_try):print('Operation error:{}'.format(err))print('Next try in:{}ms'.format(next_try))@riprova.retry(on_retry=on_retry)deftask():"""Subscribe via function callback to every retry attempt"""defevaluator(response):# Force retry operation if not a valid responseifresponse.status>=400:raiseRuntimeError('invalid response status')# or simple return True# Otherwise return False, meaning no retryreturnFalse@riprova.retry(evaluator=evaluator)deftask():"""Use a custom evaluator function to determine if the operation failed or not"""@riprova.retryasyncdeftask():"""Asynchronous coroutines are also supported :)"""Retry failed HTTP requests:importpookimportrequestsfromriprovaimportretry# Define HTTP mocks to simulate failed requestspook.get('server.com').times(3).reply(503)pook.get('server.com').times(1).reply(200).json({'hello':'world'})# Retry evaluator function used to determine if the operated failed or notdefevaluator(response):ifresponse!=200:returnException('failed request')# you can also simply return TruereturnFalse# On retry even subscriptordefon_retry(err,next_try):print('Operation error{}'.format(err))print('Next try in{}ms'.format(next_try))# Register retriable operation@retry(evaluator=evaluator,on_retry=on_retry)deffetch(url):returnrequests.get(url)# Run task that might failfetch('http://server.com')LicenseMIT - Tomas Apariciov0.3.0 / 2023-05-20Deprecate asyncio.coroutingDrop Python 2 and 3.4 supportv0.2.7 / 2018-08-24Merge pull request #20 from ffix/forward-exception-instanceCorrect linter warningsRe-raise exception instance instead of new exception with no argsMerge pull request #19 from EdwardBetts/spellingCorrect spelling mistakes.feat(setup): support Python 3.7feat(History): add version changesv0.2.6 / 2018-04-14fix(#17): handle as legit retriable error Timeout exceptions.v0.2.5 / 2018-03-21Merge pull request #15 from jstasiak/allow-newer-sixAllow newer sixfeat(History): update changesv0.2.5 / 2018-03-21Merge pull request #15 from jstasiak/allow-newer-sixAllow newer sixfeat(History): update changesv0.2.4 / 2018-03-20merge(#14): Allow subsecond maxtimes for ExponentialBackoffv0.2.3 / 2017-01-13refactor(retry): remove unnecessary partial functionfix(retry): rename keyword param for partial applicationfeat(docs): improve descriptionrefactor(Makefile): update publish taskv0.2.2 / 2017-01-06feat(package): add wheel distributionv0.2.1 / 2017-01-04fix(retrier): remove debug print statementv0.2.0 / 2017-01-02feat(core): use seconds as default time unit (introduces API breaking changes)refactor(examples): update examples to use new time unitfeat(contextmanager): adds context manager supportfeat(examples): add context manager examplefeat: add context managers supportv0.1.3 / 2016-12-30refactor(async_retrier): simplify coroutine wrapperfeat(whitelist): add whitelist and blacklist supportfeat(tests): add missing test cases for whitelistfeat(retry): pass error_evaluator paramfix(retrier): cast delay to floatfix(tests): use valid exception for Python 2.7feat(#6): add custom error whilelist and custom error evaluator functionMerge pull request #8 from tsarpaul/masterrefactor(decorator): do not expose retrier instancev0.1.2 / 2016-12-27fix(decorator): wrap retries instance per function callv0.1.1 / 2016-12-27fix(#2): handle and forwardasyncio.CancelledErroras non-retriable errorv0.1.0 / 2016-12-25First version