更多的python方法来处理嵌套的try。。。除了街区?

2024-06-03 06:19:48 发布

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

有没有一种更干净或更像Python的方法来完成以下工作?在

try:
    error_prone_function(arg1)
except MyError:
    try:
        error_prone_function(arg2)
    except MyError:
        try:
            another_error_prone_function(arg3)
        except MyError:
            try:
                last_error_prone_function(arg4)
            except MyError:
                raise MyError("All backup parameters failed.")

基本上是:如果尝试1失败,尝试2。如果#2失败,请尝试#3。如果#3失败,请尝试#4。如果#4失败。。。如果#n失败,则最终引发一些异常。在

请注意,我不一定每次都调用同一个函数,也不一定每次都使用相同的函数参数。但是,我,期望每个函数上都有相同的异常MyError。在


Tags: 方法函数anotherfunctionerrorarg3lastraise
2条回答

基于生成器的方法可能会比数据驱动方法提供更多的灵活性:

def attempts_generator():

#   try:
#       <the code you're attempting to run>
#   except Exception as e:
#       # failure
#       yield e.message
#   else:
#       # success
#       return

    try:
        print 'Attempt 1'
        raise Exception('Failed attempt 1')
    except Exception as e:
        yield e.message
    else:
        return

    try:
        print 'Attempt 2'
        # raise Exception('Failed attempt 2')
    except Exception as e:
        yield e.message
    else:
        return

    try:
        print 'Attempt 3'
        raise Exception('Failed attempt 3')
    except Exception as e:
        yield e.message
    else:
        return

    try:
        print 'Attempt 4'
        raise Exception('Failed attempt 4')
    except Exception as e:
        yield e.message
    else:
        return

    raise Exception('All attempts failed!')

attempts = attempts_generator()
for attempt in attempts:
    print attempt + ', retrying...'

print 'All good!'

这个想法是构建一个生成器,通过一个重试循环逐步通过尝试块。在

一旦生成器成功地尝试了一次,它就会用一个硬的return停止自己的迭代。不成功的尝试会导致下一次回退的重试循环。否则,如果它用尽了尝试,它最终会抛出一个无法恢复的错误。在

这里的优点是try..exceptions的内容可以是您想要的任何内容,而不仅仅是单个函数调用,如果这是由于任何原因而特别尴尬的话。生成器函数也可以在闭包中定义。在

正如我在这里所做的,产量也可以传递回日志信息。在

上面的输出,顺便说一句,我让尝试2成功了,如前所述:

^{pr2}$

如果您在尝试2中取消了对加薪的注释,那么它们都失败了,您将得到:

mbp:scratch geo$ python ./fallback.py
Attempt 1
Failed attempt 1, retrying...
Attempt 2
Failed attempt 2, retrying...
Attempt 3
Failed attempt 3, retrying...
Attempt 4
Failed attempt 4, retrying...
Traceback (most recent call last):
  File "./fallback.py", line 47, in <module>
    for attempt in attempts:
  File "./fallback.py", line 44, in attempts_generator
raise Exception('All attempts failed!')
Exception: All attempts failed!

编辑:

根据您的伪代码,如下所示:

def attempts_generator():
    try:
        error_prone_function(arg1)
    except MyError
        yield
    else:
        return

    try:
        error_prone_function(arg2)
    except MyError
        yield
    else:
        return

    try:
        another_error_prone_function(arg3)
    except MyError:
        yield
    else:
        return

    try:
        last_error_prone_function(arg4)
    except MyError:
        yield
    else:
        return

    raise MyError("All backup parameters failed.")

attempts = attempts_generator()
for attempt in attempts:
    pass

它会让任何例外,但我的错误泡沫,并停止整个事情。您还可以选择为每个块捕获不同的错误。在

多亏了johnkugelman的文章here,我决定采用这个方法,它利用for循环中不太为人所知的else子句来执行代码,当一个完整的列表被耗尽而没有break时。在

funcs_and_args = [(func1, "150mm"),
                  (func1, "100mm",
                  (func2, "50mm"),
                  (func3, "50mm"),
                  ]
for func, arg in funcs_and_args :
    try:
        func(arg)
        # exit the loop on success
        break
    except MyError:
        # repeat the loop on failure
        continue
else:
    # List exhausted without break, so there must have always been an Error
    raise MyError("Error text")

正如danielroseman在下面评论的那样,注意缩进,因为try语句有一个else子句。在

相关问题 更多 >