Сделайте максимум пять попыток, после первых четырёх ошибок ждите 1, 2, 4 и 8 секунд. После пятой ошибки пробросьте исключение.
Декоратор для автоматического повторения запросов к API
Сделайте максимум пять попыток, после первых четырёх ошибок ждите 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.