如何在Python中重复with语句的主体?

Fom*_*aut 7 python python-3.x

我想实现一种仅使用上下文管理器来重复一段代码所需次数的方法,因为它的语法很漂亮。像这样:

with try_until_success(attempts=10):
    command1()
    command2()
    command3()
Run Code Online (Sandbox Code Playgroud)

如果没有发生错误,命令必须执行一次。如果发生错误,它们应该再次执行,直到经过 10 次尝试,如果是这样,则必须引发错误。例如,重新连接到数据库可能很有用。我表示的语法是字面的,我不想修改它(所以不建议我用某种语句替换它forwhile

有没有办法用try_until_successPython实现我想要的功能?

我尝试的是:

from contextlib import contextmanager

@contextmanager
def try_until_success(attempts=None):
    counter = 0

    while True:
        try:
            yield
        except Exception as exc:
            pass
        else:
            break

        counter += 1
        if attempts is not None and counter >= attempts:
            raise exc
Run Code Online (Sandbox Code Playgroud)

这给了我错误:

RuntimeError: generator didn't stop after throw()
Run Code Online (Sandbox Code Playgroud)

我知道,有很多方法可以使用循环而不是with-statement装饰器或在装饰器的帮助下达到我的需要。但两者都有语法缺点。例如,如果是循环,我必须插入try-except块,如果是装饰器,我必须定义一个新函数。

我已经看过这些问题:

如何制作一个内部有循环的上下文管理器?

有条件地跳过 Python With 语句的主体

他们对我的问题没有帮助。

che*_*ner 2

问题是with语句的主体不在对 的调用try_until_success运行。该函数返回一个带有方法的对象__enter__;该__enter__方法调用并返回,然后with执行语句的主体。with没有规定将主体包装在任何类型的循环中,以便在到达语句末尾后可以重复主体。