Реализация повторного декоратора одним методом выше исключения - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь реализовать декоратор retry в последовательном запросе. Общая идея моего кода показана ниже. Я изо всех сил пытаюсь заставить это повториться, когда декоратор - один из методов в иерархии. Как я могу повторить метод, если он является одним из методов, вызывающих исключение?

Одна сложность, которая разочаровывает, - это мое время приращения за повтор, зависит от фактической команды. Некоторые команды требуют больше времени, чем другие. Вот почему я передал extra_time_per_retry и не смог реализовать декоратор повторных попыток с использованием традиционного стиля @retry.

FYI _serial создан в классе на init через pySerial.

Я заставил его работать с декоратором повтора прямо над методом, который выдает исключение. Я хотел бы, чтобы это было два выше, чтобы сохранить мой код в чистоте.

Я попытался передать в декоратор повторных попыток точный тип исключения, но не смог заставить его работать.

def _query_with_retries(self, cmd, extra_time_per_retry):
    _retriable_query = retry(stop_max_attempt_number=5,
                             wait_incrementing_start=self._serial.timeout + extra_time_per_retry,
                             wait_incrementing_increment=10)(self._query)
    return _retriable_query(cmd)

def _query(self, cmd):
    cmd_msg = cmd + '\r'
    self._serial.reset_input_buffer()
    self._serial.reset_output_buffer()
    self._serial.write(cmd_msg)

    return self._readlines()

def _readlines(self):
    response_str = self._serial.read_until('\r', 256)  # Max 256 bytes

    # Parse response here, if a bad one set bad_response = true

    if bad_response:
        raise ResponseError("Response had custom error xyz")

1 Ответ

0 голосов
/ 07 января 2019

Полагаю, вы могли бы упаковать свой вызов на _readlines() в блок обработки исключений, вызвав ошибку:

python 3.x

@retry
def _query(self, cmd):
    cmd_msg = cmd + '\r'
    self._serial.reset_input_buffer()
    self._serial.reset_output_buffer()
    self._serial.write(cmd_msg)

    try:
        answer = self._readlines()
    except Exception as e:
        raise e
    return answer

Python 2.x

@retry
def _query(self, cmd):
    cmd_msg = cmd + '\r'
    self._serial.reset_input_buffer()
    self._serial.reset_output_buffer()
    self._serial.write(cmd_msg)

    try:
        answer = self._readlines()
    except Exception:
        t, v, tb = sys.exc_info()
        raise t, v, tb
    return answer

Таким образом, вы ловите исключение непосредственно при его возникновении и вызываете его внутри метода, который будет повторен. Я не уверен, достаточно ли для вас этого declutters, однако это должно работать.

Некоторые могут жаловаться на использование бланка except Exception, однако, поскольку я всегда ререйзирую его, я не вижу никакого вреда.

...