Skip to main content

Easy to use retry decorator.

Project description

https://img.shields.io/pypi/dm/retry.svg?maxAge=2592000 https://img.shields.io/pypi/v/retry.svg?maxAge=2592000 https://img.shields.io/pypi/l/retry.svg?maxAge=2592000

Easy to use retry decorator.

Originally forked from https://github.com/invl/retry, since we use this library quite heavily, and the original is no longer maintained.

Features

  • No external dependency (stdlib only).

  • (Optionally) Preserve function signatures (pip install decorator).

  • Original traceback, easy to debug.

Installation

$ pip install retry

API

retry decorator

def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
    """Return a retry decorator.

    :param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
    :param tries: the maximum number of attempts. default: -1 (infinite).
    :param delay: initial delay between attempts. default: 0.
    :param max_delay: the maximum value of delay. default: None (no limit).
    :param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
    :param jitter: extra seconds added to delay between attempts. default: 0.
                   fixed if a number, random if a range tuple (min, max)
    :param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
                   default: retry.logging_logger. if None, logging is disabled.
    """

Various retrying logic can be achieved by combination of arguments.

Examples

from retry import retry
@retry()
def make_trouble():
    '''Retry until succeed'''
@retry(ZeroDivisionError, tries=3, delay=2)
def make_trouble():
    '''Retry on ZeroDivisionError, raise error after 3 attempts, sleep 2 seconds between attempts.'''
@retry((ValueError, TypeError), delay=1, backoff=2)
def make_trouble():
    '''Retry on ValueError or TypeError, sleep 1, 2, 4, 8, ... seconds between attempts.'''
@retry((ValueError, TypeError), delay=1, backoff=2, max_delay=4)
def make_trouble():
    '''Retry on ValueError or TypeError, sleep 1, 2, 4, 4, ... seconds between attempts.'''
@retry(ValueError, delay=1, jitter=1)
def make_trouble():
    '''Retry on ValueError, sleep 1, 2, 3, 4, ... seconds between attempts.'''
# If you enable logging, you can get warnings like 'ValueError, retrying in
# 1 seconds'
if __name__ == '__main__':
    import logging
    logging.basicConfig()
    make_trouble()

retry_call

def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1,
               jitter=0,
               logger=logging_logger):
    """
    Calls a function and re-executes it if it failed.

    :param f: the function to execute.
    :param fargs: the positional arguments of the function to execute.
    :param fkwargs: the named arguments of the function to execute.
    :param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
    :param tries: the maximum number of attempts. default: -1 (infinite).
    :param delay: initial delay between attempts. default: 0.
    :param max_delay: the maximum value of delay. default: None (no limit).
    :param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
    :param jitter: extra seconds added to delay between attempts. default: 0.
                   fixed if a number, random if a range tuple (min, max)
    :param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
                   default: retry.logging_logger. if None, logging is disabled.
    :returns: the result of the f function.
    """

This is very similar to the decorator, except that it takes a function and its arguments as parameters. The use case behind it is to be able to dynamically adjust the retry arguments.

import requests

from retry.api import retry_call


def make_trouble(service, info=None):
    if not info:
        info = ''
    r = requests.get(service + info)
    return r.text


def what_is_my_ip(approach=None):
    if approach == "optimistic":
        tries = 1
    elif approach == "conservative":
        tries = 3
    else:
        # skeptical
        tries = -1
    result = retry_call(make_trouble, fargs=["http://ipinfo.io/"], fkwargs={"info": "ip"}, tries=tries)
    print(result)

what_is_my_ip("conservative")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easyretry-0.9.3.dev101.tar.gz (6.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

easyretry-0.9.3.dev101-py2.py3-none-any.whl (5.7 kB view details)

Uploaded Python 2Python 3

File details

Details for the file easyretry-0.9.3.dev101.tar.gz.

File metadata

  • Download URL: easyretry-0.9.3.dev101.tar.gz
  • Upload date:
  • Size: 6.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.6

File hashes

Hashes for easyretry-0.9.3.dev101.tar.gz
Algorithm Hash digest
SHA256 9ce7759588b9cefe82f1ca3e47b7a909c57b4b4fa4a0bbc5855b09fb914a0139
MD5 d6b2237c4d1f0d41f72718497564792f
BLAKE2b-256 9987c5a65ebaf9e0d7061e75b393a38179ff01a5a5a6636a2c957119fe7de938

See more details on using hashes here.

File details

Details for the file easyretry-0.9.3.dev101-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for easyretry-0.9.3.dev101-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 1f854312628cadc59304bd8e9fb6686ba402df3aea43a68e7d1718f49a3c2ec3
MD5 01726c1010c896a6316af1dd2dcf0b4a
BLAKE2b-256 5811f8d041a188e5c033a50fee2d9706ff88e785c900feb0638d45711e4aa525

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page