【问题标题】:Can a finally block know if there was an exceptionfinally 块是否可以知道是否有异常
【发布时间】:2017-09-04 15:26:28
【问题描述】:

在 Python 程序中,我的代码具有以下结构:

try:
    value = my_function(*args)
finally:
    with some_context_manager:
        do_something()
        if 'value' in locals():
            do_something_else(value)

但是'value' in locals() 结构感觉有点脆弱,我想知道是否有更好的方法来做到这一点。

我真正想要的是finally 中的代码根据try 块是否引发异常而略有不同。有没有办法知道是否引发了异常?

【问题讨论】:

  • 我认为您想要的是另一个上下文管理器,而不是 try/finally 语法。 __exit__ 会知道是否有异常。
  • 您也可以使用else 块,它仅在没有引发异常时运行。
  • @AshwiniChaudhary else 块将在 finally 块之前运行,这会改变 OP 代码的语义。
  • @AshwiniChaudhary 但我只想在没有异常时运行的代码位于finally 块调用的上下文管理器中。
  • do_something 一定要在 my_functionmy_function 之后运行吗?

标签: python exception try-finally


【解决方案1】:

如果目标是“当引发异常时,做一些不同的事情”,那么:

exception_raised = False
try:
    value = my_function(*args)
except:
    exception_raised = True
    raise
finally:
    with some_context_manager:
        do_something()
        if not exception_raised:
            do_something_else(value)

现在,如果您要处理多个异常并实际处理,我建议:

completed_successfully = False
try:
    value = my_function(*args)
else:
    completed_successfully = True
finally:
    with some_context_manager:
        do_something()
        if completed_sucessfully:
            do_something_else(value)

【讨论】:

    【解决方案2】:

    这里有几个想法:

    在尝试之前设置值:

    value = None
    try:
        value = my_function(*args)
    finally:
        with some_context_manager:
            do_something()
            if value is not None:
                do_something_else(value)
    

    或者如果你想根据异常类型设置值:

    try:
        value = my_function(*args)
    except:
        value = None
        raise
    finally:
        with some_context_manager:
            do_something()
            if value is not None:
                do_something_else(value)
    

    【讨论】:

    • 我不想捕获my_function引发的异常,但是无论是否有异常都需要进行清理,这就是我使用finally的原因。
    • 我已经删除了第三个会捕获异常的选项并调整了选项 2...感谢您的澄清
    • 您假设my_function 永远不会返回None,这使得您的解决方案不如answermwchase 通用。但是你的稍微短一些,所以我可能最终还是会使用它,因为my_function 恰好只返回字符串。 (不过我会删除 ' 字符)。
    • 好点,我同意 mwchase 的回答更笼统。如果我第一次看时他在那儿,我就不会写了。我错过了 ' 字符,我会编辑。
    【解决方案3】:

    将异常分配给 except 套件中的变量,然后在 finally 套件中使用它。

    foo = False
    try:
        raise KeyError('foo not found')
    except KeyError as e:
        pprint(e)
        foo = e
    finally:
        if foo:
            print(foo)
        else:
            print('NO')
    

    【讨论】:

    • 如果没有KeyError,您的代码将引发NameError
    • 现在如果在try 块的最后一行之前发生不是KeyError 的异常,则不会初始化foo
    • 老鼠...这甚至可行吗? foo 是否会在 finally 套件中的上下文管理器内部范围内?
    • 你可以在 try 块之外初始化它。
    猜你喜欢
    • 2010-09-16
    • 2013-02-23
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    相关资源
    最近更新 更多