паттерны· 3 мин

Крошечный декоратор для повторов

Сетевые вызовы иногда падают по случайным причинам, и хочется просто повторить попытку. В большинстве проектов для этого не нужна отдельная библиотека — достаточно небольшого декоратора с экспоненциальной задержкой.

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. Но для скрипта или одного сервиса показанного варианта обычно хватает.

Полезные доработки, которые можно добавить за пару строк:

  • случайный джиттер, чтобы не бить по серверу синхронно;
  • логирование номера попытки;
  • отдельный список «повторяемых» исключений (как в примере выше).

← ко всем заметкам