Декоратор с автоматическим повтором при исключении

Определите times как общее число попыток, возвращайте результат первого успеха, а после последней ошибки используйте raise для проброса исходного исключения.

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

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

Определите times как общее число попыток, возвращайте результат первого успеха, а после последней ошибки используйте raise для проброса исходного исключения.

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

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

Условие

Создайте декоратор, который при возникновении ошибки будет пытаться выполнить оборачиваемую функцию ещё несколько раз. Количество попыток задаётся параметром декоратора. Если функция успешно отработает в течение этих попыток, необходимо вернуть её результат. Если же после всех попыток ошибка сохраняется, следует пробросить её дальше.

Пример использования:

@retry(times=3)
def unreliable_func():
    # код, который может бросить исключение
    ...

Ответ

Определите times как общее число попыток, возвращайте результат первого успеха, а после последней ошибки используйте raise для проброса исходного исключения.

from functools import wraps

def retry(times):
    if type(times) is not int or times < 1:
        raise ValueError('Нужно хотя бы одно выполнение')
    def decorate(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(times):
                try:
                    return func(*args, **kwargs)
                except Exception:
                    if attempt == times - 1:
                        raise
        return wrapper
    return decorate

В production ограничьте список повторяемых ошибок и добавьте задержку с backoff. Повторы изменяющих операций безопасны только при идемпотентности или проверке уже выполненного действия. Для async-функции нужен async-декоратор, иначе исключения выполнения корутины не будут перехвачены.

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

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

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

Подробнее