Декоратор для автоматического повторения запросов к API

Сделайте максимум пять попыток, после первых четырёх ошибок ждите 1, 2, 4 и 8 секунд. После пятой ошибки пробросьте исключение.

Короткий ответ

Что ответить на собеседовании

Сделайте максимум пять попыток, после первых четырёх ошибок ждите 1, 2, 4 и 8 секунд. После пятой ошибки пробросьте исключение.

Подробный разбор

Ответ с пояснениями

Условие

Создайте декоратор, который при возникновении исключений будет повторно вызывать обернутую функцию. Задержка между попытками должна увеличиваться экспоненциально (по формуле 2^n секунд). Декоратор обязан фиксировать каждую неудачную попытку в лог и прекращать попытки после пяти неудачных запусков либо при успешном завершении функции.

Ответ

Сделайте максимум пять попыток, после первых четырёх ошибок ждите 1, 2, 4 и 8 секунд. После пятой ошибки пробросьте исключение.

import logging
import time
from functools import wraps

logger = logging.getLogger(__name__)

def retry_api(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        for attempt in range(5):
            try:
                return func(*args, **kwargs)
            except Exception as error:
                logger.warning('Попытка %s неуспешна: %s',
                               attempt + 1, type(error).__name__)
                if attempt == 4:
                    raise
                time.sleep(2 ** attempt)
    return wrapper

Отсчёт n начинается с нуля. В production сужайте перехватываемые исключения до временных сбоев, учитывайте Retry-After и идемпотентность. Ошибки валидации повторять бессмысленно. Для async-функции необходимы await и asyncio.sleep, иначе блокируется event loop.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее