Определите 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-декоратор, иначе исключения выполнения корутины не будут перехвачены.