Typical situation: you have unreliable function, for example, doing HTTP requests and getting exception from time to time. Maybe connection went down temporary or 429 Too Many requests problem, or remote service itself is temporary broken.
One simple decorator solves problem:
import functools
def retry(num_times=1):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
last_exception = None
for n in range(num_times):
try:
r = func(*args, **kwargs)
except Exception as e:
last_exception = e
# handle exception. log it or just pass
print(f"Try #{n} got exception {e}, but we will retry")
else:
return r
raise last_exception
return wrapper_repeat
return decorator_repeat
Lets use it with requests:
import requests
@retry(10)
def myhttp():
r = requests.get('https://httpbin.org/status/200,500,429')
r.raise_for_status()
print(r.status_code)
myhttp()
Results:
Try #0 got exception 429 Client Error: TOO MANY REQUESTS for url: https://httpbin.org/status/200,500,429, but we will retry
Try #1 got exception 500 Server Error: INTERNAL SERVER ERROR for url: https://httpbin.org/status/200,500,429, but we will retry
Try #2 got exception 500 Server Error: INTERNAL SERVER ERROR for url: https://httpbin.org/status/200,500,429, but we will retry
200
This way you are immune against temporary problems which could be solved by retry (maybe with time.sleep(10)
) but you will still get exception from long-time problems. Change URL in myhttp()
to https://httpbin.org/status/500 to see this.
Top comments (0)