在函数内部,我使用类似的重试机制(总是在try / except块中):
def load(self):
[........]
# Retry mechanism for locking database
for i in range(1, max_connection_retries+1):
try:
cu.lock()
break
except LockError as l_error:
if i < max_connection_retries:
sleep(20)
continue
else:
raise ContinuableError (logger.console(datetime.now().time().strftime ("%b %d %H:%M:%S") + ' ERROR:Impossible to lock the database after %i retries' % max_connection_retries))
[.......]
我在相同功能的其他部分和其他功能中多次使用此机制。可以将装饰器仅应用于代码的这一部分吗?类似的东西:
def load(self):
[.......]
@retry(max=5,message='blablabla')
try:
cu.lock()
break
except LockError as l_error:
[.......]
@retry(max=5)
try:
cu.unlock()
break
except LockError as l_error:
如果是这样,你能帮我展示一个装饰师做这样的任务的例子吗?
答案 0 :(得分:3)
装饰器语法只是
的语法糖# f could be a class as well
def f():
...
f = retry(f)
它不能应用于任意匿名代码块。装饰器的主要目的是重新绑定名称,根据定义,匿名块没有名称。
您需要做的是将要重试的代码重构为一个被装饰的函数。例如,
@retry(max=5, message='blablabla')
def get_lock():
try:
cu.lock()
except LockError as l_error:
# Some action dependent on the implementation of retry
def load(self):
get_lock()
答案 1 :(得分:2)
由于所述装饰器只能应用于功能,但可以移动&#34;重试&#34;分离函数的逻辑并将cu.lock
/ cu.unlock
(以及max
,messge
等其他内容)传递给该函数作为参数:
def retry(func, tries, message):
for i in range(1, tries+1):
try:
func() # <- call passed function
break
except LockError as l_error:
if i < tries:
sleep(20)
continue
else:
raise ContinuableError('...')
def load(self):
retry(cu.lock, tries=5, message='blablabla') # pass cu.lock to be called
retry(cu.unlock, tries=5, message='blablabla') # pass cu.unlock to be called