实现重试装饰器一种高于异常的方法
Implementing retry decorator one method higher than exception
我正在尝试对串行查询实施 retry decorator。我的代码的总体思路如下所示。当装饰器是层次结构中的一种方法时,我正在努力让它重试。当它是抛出异常的方法的上一个方法时,如何重试该方法?
一个令人沮丧的并发症是我每次重试的增量时间取决于实际命令。有些命令比其他命令需要更多时间。这就是为什么我传入了 extra_time_per_retry,并且无法使用传统的 @retry 样式实现重试装饰器。
仅供参考,_serial 是通过 pySerial 在 init 上的 class 中创建的。
我让它与抛出异常的方法正上方的重试装饰器一起工作。我希望它在上面两个以保持我的代码干净。
我已经尝试为重试装饰器提供确切的异常类型,但无法让它工作。
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")
我想您可以将对 _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
,但是因为我总是立即重新加注,所以我看不出有什么坏处。
我正在尝试对串行查询实施 retry decorator。我的代码的总体思路如下所示。当装饰器是层次结构中的一种方法时,我正在努力让它重试。当它是抛出异常的方法的上一个方法时,如何重试该方法?
一个令人沮丧的并发症是我每次重试的增量时间取决于实际命令。有些命令比其他命令需要更多时间。这就是为什么我传入了 extra_time_per_retry,并且无法使用传统的 @retry 样式实现重试装饰器。
仅供参考,_serial 是通过 pySerial 在 init 上的 class 中创建的。
我让它与抛出异常的方法正上方的重试装饰器一起工作。我希望它在上面两个以保持我的代码干净。
我已经尝试为重试装饰器提供确切的异常类型,但无法让它工作。
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")
我想您可以将对 _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
,但是因为我总是立即重新加注,所以我看不出有什么坏处。