Skip to main content

Rever, a retrying decorator

Project description

Rever, A retrying decorator

A retry decorator can be useful in many situations. One example is when scraping web pages. Suppose you have a function that retrieves the status code response of a GET request. If the status code returns 200, then you are happy. But if not, then there here is what you might do:

  1. You could write your retrying logic directly into your functions

    >>> def get_response(webpage):
    >>>     response = function_to_get_webpage(webpage)
    >>>     status_code = function_to_get_status_code(response)
    >>>     if status_code == 200:
    >>>         return status_code
    >>>     else:
    >>>         time.sleep(3)
    >>>         num_tries -= 1
    >>>         if num_tries > 0:
    >>>             return get_response(webpage)
    >>>
    >>> if __name__ == "__main__":
    >>>     num_tries = 2
    >>>     get_response("http://www.google.com")
    
  2. You could use a retrying decorator like rever

    >>> from rever import rever
    >>> @rever(times=2, pause=3, exception=MyException, raises=False)
    >>> def get_response(webpage):
    >>>     response = function_to_get_webpage(webpage)
    >>>     status_code = function_to_get_status_code(response)
    >>>     if status_code == 200:
    >>>         return status_code
    >>>     else:
    >>>         raise MyException
    >>>
    >>> if __name__ == "__main__":
    >>>     get_response("http://www.google.com")
    

In the first example, you need to write out the retrying logic yourself. The second example it is taken care of in the decorator; a nice way of keeping things separate.

Installation

$ pip install rever

Keyword Arguments

The rever decorator takes only keyword arguments.

Possible keyword arguments:

backoff:

description: if True subsequent pauses for each retry will increase exponentially

possible values: boolean

total_pause:

description: the total time you are willing to wait for all of your pauses between retrys

possible values: integer or float

steps:

description: related to backoff and is set at 10 because wikipedia says so: https://en.wikipedia.org/wiki/Exponential_backoff

possible values: integer

exception:

description: you can choose which exception or exceptions to catch

possible values: any Exception that gets raised by Python

raises:

description: if all the retrys fail, do you want to raise an exception or not?

possible values: boolean

prior:

description: if you want to call another function/script prior to retrying, you can do so but without any args or kwargs

possible values: a simple function…cannot take args or kwargs

These arguments are used if *backoff* is set to False:

times:

description: the number of times you want the function to retry

possible values: integer

pause:

description: the number of seconds you want to pause before your function retrys

possible values: integer or float

Examples & Explanation

default

Default behavior

>>> @rever()
  • rever will use exponential backoff

  • rever will have a total pause time of 30 seconds (total time your function will pause)

  • rever will have 10 steps (steps here means the number of times your function will retry)

  • rever will catch any exception

  • rever will ultimately raise an exception if all retrys fail

exception

Catch one specific exception

>>> @rever(exception=TypeError)
>>> @rever(exception=(TypeError, ))
  • rever will use exponential backoff

  • rever will have a total pause time of 30 seconds (total time your function will pause)

  • rever will have 10 steps (steps here means the number of times your function will retry)

  • rever will catch only TypeError

  • rever will ultimately raise an exception if all retrys fail

Catch one of multiple specific exceptions

>>> @rever(exception=(TypeError, ConnectionError))
  • rever will use exponential backoff

  • rever will have a total pause time of 30 seconds (total time your function will pause)

  • rever will have 10 steps (steps here means the number of times your function will retry)

  • rever will catch any of only TypeError or ConnectionError

  • rever will ultimately raise an exception if all retrys fail

raises

Raise an exception or do not

>>> @rever(raises=False)
  • rever will use exponential backoff

  • rever will have a total pause time of 30 seconds (total time your function will pause)

  • rever will have 10 steps (steps here means the number of times your function will retry)

  • rever will catch any exception

  • rever will ultimately not raise an exception if all retrys fail

prior

Call a function prior to retrying

>>> @rever(prior=some_function_to_call_prior_to_retyring)
  • rever will use exponential backoff

  • rever will have a total pause time of 30 seconds (total time your function will pause)

  • rever will have 10 steps (steps here means the number of times your function will retry)

  • rever will catch any exception

  • rever will ultimately raise an exception if all retrys fail

  • rever will call some function prior to each retry

Below used only if backoff is set to False, it is included for backwards compatibility

times

Retry a certain number of times

>>> @rever(backoff=False, times=10)
  • rever will not use exponential backoff

  • rever will have a total pause time of 0 seconds (total time your function will pause)

  • rever will retry 1 time (time here means the number of times your function will retry)

  • rever will catch any exception

  • rever will ultimately raise an exception if all retrys fail

pause

Pause for some number of seconds between each retry

>>> @rever(backoff=False, pause=5)
  • rever will not use exponential backoff

  • rever will have a total pause time of 5 seconds (total time your function will pause)

  • rever will retry 1 time (time here means the number of times your function will retry)

  • rever will catch any exception

  • rever will ultimately raise an exception if all retrys fail

You can basically use any combination of keywords you would like

Testing

To run tests, clone the github repository:

$ git clone https://github.com/liamcryan/rever $ cd rever $ pip install pytest $ pytest

History

version 0.3.3 (5/12/2020)

  • fix bad link in __version__

version 0.3.2 (5/12/2020)

  • fix non-local rever_kwargs

  • change structure from multiple to files to one __init__ file

  • update README.rst with installation instructions

version 0.3.1 (7/13/2018)

  • found bug when calling the same decorated function multiple times. In certain cases the ‘times’ keyword argument decreased to 0 triggering a ReachedMaxRetries exception despite the function only being called once

version 0.3.0 (8/23/2017)

  • wanted to modify behaviour to exponential backoff as default rather than fixed intervals between retrys

  • to replicate functionality of previous versions include a kwarg backoff=False in your decorator

version 0.2.1 (8/8/2017)

  • realized that any function wanting to return any value would return None, so fixed that :)

version 0.2.0 (6/26/2017)

  • specify a function to call prior to retrying

  • realized that the retry count was off by 1, now it should be correct

version 0.1.0 (6/24/2017)

  • specify whether to raise exception after all retry attempts

  • included some testing

  • default pause is now zero seconds

version 0.0.1 (6/23/2017)

  • retry decorator

  • specify number of times to retry

  • specify number of seconds to wait

  • specify which exceptions to catch

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

rever-0.3.3.tar.gz (5.5 kB view details)

Uploaded Source

Built Distribution

rever-0.3.3-py3-none-any.whl (5.3 kB view details)

Uploaded Python 3

File details

Details for the file rever-0.3.3.tar.gz.

File metadata

  • Download URL: rever-0.3.3.tar.gz
  • Upload date:
  • Size: 5.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.7.6

File hashes

Hashes for rever-0.3.3.tar.gz
Algorithm Hash digest
SHA256 958559c8e2d9cdecb26e4184642f7a65e5c02051a1629d07d6b3ef0fc731539c
MD5 48a177107c89cf6242ea54a09f2b8160
BLAKE2b-256 bac7b3682f108bebcb455f2c56240a03e725d956c897ee947eca9f8257913cdf

See more details on using hashes here.

File details

Details for the file rever-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: rever-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 5.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.7.6

File hashes

Hashes for rever-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2b69bd02fab2b57cb29cd31c017a56d7546ea1a11896c327ca44d8693236b4b8
MD5 2fa0bb72195ee7b10e44f3232209f964
BLAKE2b-256 90b18253594d0027f74e6735540d8691c9b253e45e6259bda29e8f493772c05b

See more details on using hashes here.

Supported by

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