python - 是否可以重试一段特定的代码而不考虑异常?

标签 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 来简化“try ... except ...”部分,方法是:

# 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

最佳答案

只需要写一个装饰器,它可以同时处理循环和异常忽略部分,就像这样

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))

它不断尝试将当前值添加到 outer_a 并且只有当它大于或等于 4 时才可以添加到它。因此,它不断重试直到最大尝试次数筋疲力尽。它捕获抛出的异常,将其打印到标准输出并重试。所以,输出将是

Error : [Cannot add with 1], Retrying Attempt 1...
Error : [Cannot add with 2], Retrying Attempt 2...
Error : [Cannot add with 3], Retrying Attempt 3...
4

注意:有一个名为retrying的开源库它以更好和更灵活的方式完成相同的任务。如果可能,您可能希望检查并使用它而不是滚动您自己的装饰器。不要重复自己:-)

关于python - 是否可以重试一段特定的代码而不考虑异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28757327/

相关文章:

python - 在python中将字典转换为数据框

python - 属性错误 : 'RegexURLPattern' object has no attribute '_callback'

Python GUI实现方向

python - 在 Python 中装饰每个实例的方法

c# - 使抽象方法具有覆盖的主体

python - 如何使用 joblib.Memory 缓存 Python 类的成员函数的输出

python - 在 Python 中创建 Zigzag 数组的函数

管理生成器的 Pythonic 方式

python - 根据条件使用不同的上下文管理器

python - 如何调用 contextmanager 忽略产生的值(在一行中)?