rtry
Installation
pip3 install rtry
Documentation
Timeout
As context manager
from rtry import timeout, CancelledError
try:
with timeout(3.0):
resp = requests.get("https://httpbin.org/status/200")
except CancelledError:
raise
else:
print(resp)
As context manager (silent)
from rtry import timeout, CancelledError
resp = None
with timeout(3.0, exception=None):
resp = requests.get("https://httpbin.org/status/200")
As context manager (asyncio)
import asyncio
import aiohttp
from rtry import timeout, CancelledError
async def main():
try:
async with aiohttp.ClientSession() as session, timeout(3.0):
async with session.get("https://httpbin.org/status/200") as resp:
return resp
except CancelledError:
raise
else:
print(resp)
asyncio.run(main())
As decorator
from rtry import timeout, CancelledError
@timeout(3.0)
def fn():
resp = requests.get("https://httpbin.org/status/200")
return resp
try:
resp = fn()
except CancelledError:
raise
else:
print(resp)
As decorator (asyncio)
import asyncio
import aiohttp
from rtry import timeout, CancelledError
@timeout(3.0)
async def fn():
async with aiohttp.ClientSession() as session:
async with session.get("https://httpbin.org/status/200") as resp:
return resp
async def main():
try:
resp = await fn()
except CancelledError:
raise
else:
print(resp)
asyncio.run(main())
As argument
from rtry import retry, CancelledError
@retry(until=lambda r: r.status_code != 200, timeout=3.0)
def fn():
resp = requests.get("https://httpbin.org/status/200")
return resp
try:
resp = fn()
except CancelledError:
raise
else:
print(resp)
Retry
Attempts
@retry(attempts=2)
def fn():
resp = requests.get("https://httpbin.org/status/500")
print(resp)
assert resp.status_code == 200
return resp
resp = fn()
# <Response [500]>
# <Response [500]>
# Traceback:
# AssertionError
Until
@retry(until=lambda r: r.status_code != 200, attempts=2)
def fn():
resp = requests.get("https://httpbin.org/status/500")
print(resp)
return resp
resp = fn()
# <Response [500]>
# <Response [500]>
Logger
Simple logger
@retry(until=lambda r: r.status_code != 200, attempts=2, logger=print)
def fn():
resp = requests.get("https://httpbin.org/status/500")
return resp
resp = fn()
# 1 <Response [500]> <function fn at 0x103dcd268>
# 2 <Response [500]> <function fn at 0x103dcd268>
Custom logger
def logger(attempt, result_or_exception, decorated):
logging.info("Attempt: %d, Result: %s", attempt, result_or_exception)
@retry(until=lambda r: r.status_code != 200, attempts=2, logger=logger)
def fn():
resp = requests.get("https://httpbin.org/status/500")
return resp
resp = fn()
# INFO:root:Attempt: 1, Result: <Response [500]>
# INFO:root:Attempt: 2, Result: <Response [500]>
Delay
Const delay
@retry(until=lambda r: r.status_code != 200, attempts=2, delay=0.1)
def fn():
resp = requests.get("https://httpbin.org/status/500")
return resp
started_at = time.monotonic()
resp = fn()
ended_at = time.monotonic()
print('Elapsed {:.2f}'.format(ended_at - started_at))
# Elapsed 2.11
Custom delay
from math import exp
@retry(until=lambda r: r.status_code != 200, attempts=2, delay=exp)
def fn():
resp = requests.get("https://httpbin.org/status/500")
return resp
started_at = time.monotonic()
resp = fn()
ended_at = time.monotonic()
print('Elapsed {:.2f}'.format(ended_at - started_at))
# Elapsed 11.79
Swallow
Fail on first exception
@retry(attempts=2, swallow=None, logger=print)
def fn():
resp = requests.get("http://127.0.0.1/status/500")
return resp
try:
resp = fn()
except Exception as e:
print(e)
# HTTPConnectionPool(host='127.0.0.1', port=80): Max retries exceeded with url: /status/500
Swallow only ConnectionError
from requests.exceptions import ConnectionError
@retry(attempts=2, swallow=ConnectionError, logger=print)
def fn():
resp = requests.get("http://127.0.0.1/status/500")
return resp
try:
resp = fn()
except Exception as e:
print(e)
# 1 HTTPConnectionPool(host='127.0.0.1', port=80): Max retries exceeded with url: /status/500
# 2 HTTPConnectionPool(host='127.0.0.1', port=80): Max retries exceeded with url: /status/500
# HTTPConnectionPool(host='127.0.0.1', port=80): Max retries exceeded with url: /status/500
AsyncIO
import asyncio
import aiohttp
from rtry import retry
@retry(attempts=2)
async def fn():
async with aiohttp.ClientSession() as session:
async with session.get("https://httpbin.org/status/500") as resp:
print(resp)
assert resp.status == 200
return resp
async def main():
resp = await fn()
# <ClientResponse(https://httpbin.org/status/500) [500 INTERNAL SERVER ERROR]>
# <ClientResponse(https://httpbin.org/status/500) [500 INTERNAL SERVER ERROR]>
# Traceback
# AssertionError
asyncio.run(main())
Metadata
Release files for rtry 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| rtry-1.5.0.tar.gz | 14.4 kB | Without provenance | Details for rtry-1.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| rtry-1.5.0-py3-none-any.whl | Python 3 | none | any | Details for rtry-1.5.0-py3-none-any.whl |
Total release size: 22.9 kB
Release files / rtry-1.5.0.tar.gz
| Download URL | rtry-1.5.0.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c9dcae88ebdfe9e4f45a4a7f1d3d0a6321bef3a5a908fa99d80bdde73056cb35
|
|
BLAKE2b-256 checksum How to use checksums |
a26b7bd5da0d8432fa3726e90966b2939d06a02b0d4c906b93d118c38255547c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.12
|
Release files / rtry-1.5.0-py3-none-any.whl
| Download URL | rtry-1.5.0-py3-none-any.whl |
|---|---|
| Size | 8.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6c71d8b6cf0d2bf44484cea6afd1faa9390f5803a92faef5b65e4f292f30c65a
|
|
BLAKE2b-256 checksum How to use checksums |
256242a9f61be687909f809fcab349a80b4dab3452290f96452b934f60a65bcf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.12
|
Security for rtry 1.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.