Python 是否可以在不考虑异常的情况下重试特定代码段?
在我的Python项目中,有很多代码如下所示:Python 是否可以在不考虑异常的情况下重试特定代码段?,python,decorator,contextmanager,Python,Decorator,Contextmanager,在我的Python项目中,有很多代码如下所示: # the codes I with to simplify for _ in range(3): try: # do something break except: print "Exception. Retrying..." continue else: print "ERROR!" 我知道我可以使用contextmanager简化“尝试…除了…”部分,
# the codes I with to simplify
for _ in range(3):
try:
# do something
break
except:
print "Exception. Retrying..."
continue
else:
print "ERROR!"
我知道我可以使用contextmanager简化“尝试…除了…”部分,方法如下:
# define the exception handler function first
@contextmanager
def ignore_exception():
try:
yield
except:
print "Exception. Retrying..."
continue
# then use "with" to simplify the codes
with ignore_exception:
# do something
但是,我不能以相同的方式添加“for”循环,即
# define the exception handler function with for loop first
@contextmanager
def ignore_exception():
try:
for _ in range(3):
yield
break
else:
print "ERROR!"
except:
print "Exception. Retrying..."
continue
# then use "with" to simplify the codes
with ignore_exception:
# do something
将引发一个异常:
/usr/lib/python2.7/contextlib.pyc in __exit__(self, type, value, traceback)
26 return
27 else:
---> 28 raise RuntimeError("generator didn't stop")
29 else:
30 if value is None:
RuntimeError: generator didn't stop
有没有办法克服这种错误并将我的代码简化为:
# ideal codes
with xxxxxx: # don't have to use "with" statement
# do something
只需编写一个decorator,它可以处理循环和异常忽略部分,如下所示
def trys(maximum_tries=3):
def decorator(func):
def inner(*args, **kwargs):
for _ in range(1, maximum_tries + 1):
try:
return func(*args, **kwargs)
except ArithmeticError, e:
print("Error : [{}], Retrying Attempt {}...".format(e, _))
else:
break
return inner
return decorator
outer_a = 0
@trys(maximum_tries=4)
def adder(a):
global outer_a
outer_a += 1
if outer_a < 4:
raise ArithmeticError("Cannot add with {}".format(outer_a))
else:
return a + outer_a
print(adder(0))
现在,您可以这样调用它
def trys(maximum_tries=3):
def decorator(func):
def inner(*args, **kwargs):
for _ in range(1, maximum_tries + 1):
try:
return func(*args, **kwargs)
except ArithmeticError, e:
print("Error : [{}], Retrying Attempt {}...".format(e, _))
else:
break
return inner
return decorator
outer_a = 0
@trys(maximum_tries=4)
def adder(a):
global outer_a
outer_a += 1
if outer_a < 4:
raise ArithmeticError("Cannot add with {}".format(outer_a))
else:
return a + outer_a
print(adder(0))
注意:有一个名为的开源库,它以更好、更灵活的方式完成相同的任务。如果可能,您可能希望检查并使用它,而不是滚动您自己的装饰程序。不要重复你自己:-)这意味着我必须将所有内容都放在函数中才能使用装饰器。有没有一种方法可以避免像宏在C/C++中所能做的那样使用函数。例如,我只想重试第n到n+10行3次,然后重试第n+11到n+20行2次。为什么contextmanager不允许在内部使用循环?