Крошечный декоратор для повторов
Сетевые вызовы иногда падают по случайным причинам, и хочется просто повторить попытку. В большинстве проектов для этого не нужна отдельная библиотека — достаточно небольшого декоратора с экспоненциальной задержкой.
import time, functools
def retry(times=3, delay=0.5, exceptions=(Exception,)):
def deco(fn):
@functools.wraps(fn)
def wrap(*a, **kw):
for i in range(times):
try:
return fn(*a, **kw)
except exceptions:
if i == times - 1:
raise
time.sleep(delay * (2 ** i))
return wrap
return deco
Когда этого мало
Если нужен джиттер, лимит по суммарному времени или асинхронная версия — лучше взять tenacity. Но для скрипта или одного сервиса показанного варианта обычно хватает.
Полезные доработки, которые можно добавить за пару строк:
- случайный джиттер, чтобы не бить по серверу синхронно;
- логирование номера попытки;
- отдельный список «повторяемых» исключений (как в примере выше).