尝试(反复)捕捉异常的python方法

2024-04-16 09:38:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个脚本在无人值守的机器上运行。如果脚本抛出了一个错误,我希望记录错误,并在可行的情况下继续运行。这是我的第一个代码草案,但是由于下面解释的原因它不能工作。(请注意:如果在T秒内捕获到N个错误,则更实际的concede函数将返回true。什么的。)

from contextlib import contextmanager

@contextmanager
def perseverance(concede = lambda: False):
    while (True):
        try:
            yield
        except Exception, e:
            if (concede()):
                log_exception(e, "conceding")
                raise
            else:
                log_exception(e, "retrying")

这可以让我做一些类似的事情:

^{pr2}$

这不起作用,因为@contextmanager对异常处理很挑剔。此代码将失败:

^{3}$

我可以简单地重写persistence()以不使用上下文管理器,但不使用它优雅的语法,如下所示:

def with_perseverance(fn, concede = lambda: False):
    while (True):
        try:
            fn()
        except Exception, e:
            if (concede()):
                log_exception(e, "conceding")
                raise
            else:
                log_exception(e, "retrying")

这样称呼:

with_perseverance(do_complex_script, quit_after(3))

问题

冒着因过于主观而被否决的风险:有没有更好/更像Python的写作方式?在


Tags: lambda代码脚本logfalsetruedef错误
1条回答
网友
1楼 · 发布于 2024-04-16 09:38:42

contextmanager对异常处理并不挑剔;它只希望您只yield一次。上下文管理器不支持重入。在

如果你想要的话,你有几个选择。一种是使用with-for组合:

from contextlib import contextmanager

class MutableValue:
    def __init__(self, value):
        self.value = value

@contextmanager
def null_context():
    yield

@contextmanager
def catch_and_log(mutable_return_successful):
    try:
        yield
    except Exception as e:
        print("ERROR:", e)
    else:
        mutable_return_successful.value = True

def quit_after(n):
    for _ in range(n-1):
        successful = MutableValue(False)
        yield catch_and_log(successful)
        if successful.value:
            return

    yield null_context()

for ctx in quit_after(5):
    with ctx:
        1/0

#>>> ERROR: division by zero
#>>> ERROR: division by zero
#>>> ERROR: division by zero
#>>> ERROR: division by zero
#>>> Traceback (most recent call last):
#>>>   File "", line 31, in <module>
#>>> ZeroDivisionError: division by zero

因为with需要与for通信,所以我不得不做一些黑客工作以获得正确的返回。它仍然比基于类的解决方案更具可读性。在

另一个更容易的选择是虐待装饰师:

^{pr2}$

相关问题 更多 >