Как несколько раз повторить блок Try Except

Рейтинг: 0Ответов: 3Опубликовано: 04.04.2023

У меня есть функция, которая создает подключаение к устройству. Устройство может не ответить, тогда функция упадет с ошибкой. Как я могу в блоке try except реализовать 5 попыток подключения с интервалом в 1 секунду. То есть нужно сделать try, затем, если подключение успешно, программа идет дальше, а если не успешно, ждет секунду и снова try. И так 5 раз. Если на 5 раз поключение не успешно, тогда выводится сообщение об ошибке. Понятно, что можно сделать вложением одного блока try ecxept в другой, но не хотелось бы иметь целых 5 вложений. В голову приходит только что-то вот такое.

def get_result():
    for i in range(5):
        try:
            connection = make_connection()
        except:
            if i == 4:
                print('ошибка подключения')
                return
            else:
                sleep(1)
        else:
            break
    # и далее продолжение программы...
    result = connection.read()
    return result

Ответы

▲ 2Принят

Красивое решение - использование декоратора @retry. Ваш код выполняете в виде функции и перед именем функции ставите декоратор @retry(num_retries=3, exception_to_check=ValueError, sleep_time=0)

К примеру что-то такое:

import random
import time
from functools import wraps

def retry(num_retries, exception_to_check, sleep_time=0):
    """
    Decorator that retries the execution of a function if it raises a specific exception.
    """
    def decorate(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for i in range(1, num_retries+1):
                try:
                    return func(*args, **kwargs)
                except exception_to_check as e:
                    print(f"{func.__name__} raised {e.__class__.__name__}. Retrying...")
                    if i < num_retries:
                        time.sleep(sleep_time)
            # Raise the exception if the function was not successful after the specified number of retries
            raise e
        return wrapper
    return decorate

@retry(num_retries=3, exception_to_check=ValueError, sleep_time=1)
def random_value():
    value = random.randint(1, 5)
    if value == 3:
        raise ValueError("Value cannot be 3")
    return value
random_value()
# random_value raised ValueError. Retrying...
# 1

random_value()
# 5

Взято отсюда https://vc.ru/u/1389654-machine-learning/604457-12-dekoratorov-python-kotorye-vyvedut-vash-kod-na-novyy-uroven Но можно и попроще взять отсюда https://habr.com/ru/companies/otus/articles/666016/

def retry(max_retries):
    def retry_decorator(func):
        def _wrapper(*args, **kwargs):
            for _ in range(max_retries):
                try:
                    func(*args, **kwargs)
                except:
                    time.sleep(1)
        return _wrapper
    return retry_decorator

@retry(2)
def might_fail():
    print("might_fail")
    raise Exception
▲ 3
def get_result(retry=5):
    try:
        connection = make_connection()
    except:
        if retry:
            sleep(1)
            return get_result(retry-1)
        else:
            raise 
    result = connection.read()
    return result
▲ 1
import time
counter = 0    
while True:
    try:
        connection = make_connection()
    except:
        if counter > 5:
            print('Ошибка подключения')
            break
        else:
            counter += 1
            time.sleep(1)

С использованием for:

for i in range(5):
    try:
        connection = make_connection()
        break
    except:
        time.sleep(1)
else:
    print('Ошибка подключения')