实现重试修饰器一种比异常高的方法

时间:2019-01-07 17:15:02

标签: python pyserial python-decorators

我正在尝试在串行查询上实现retry decorator。我的代码的总体思路如下所示。当装饰器是层次结构中的一种方法时,我正在努力使其重试。如果该方法是引发异常的方法中的一种,该如何重试该方法?

一个令人沮丧的并发症是每次重试的增量时间取决于实际命令。一些命令比其他命令需要更多时间。这就是为什么我传入了extra_time_per_retry,并且无法使用传统的@retry样式实现重试装饰器的原因。

仅供参考,_serial是通过pySerial在 init 上的类中创建的。

我让它与引发异常的方法正上方的重试装饰器一起使用。我希望上面两个可以保持我的代码干净。

我尝试为重试装饰器提供确切的异常类型,但是无法正常工作。

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 :(得分:1)

我想您可以将对_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

这样,您可以在发生异常时直接捕获异常,并将其引发到将重试的方法中。我不确定这对您是否足够整理,但是应该可以。

有些人可能会抱怨使用空白的except Exception,但是由于我总是立即加注,因此看不到任何危害。