【问题标题】:What could be practical examples of using finally in the try block in Python [duplicate]在 Python 的 try 块中使用 finally 的实际示例是什么 [重复]
【发布时间】:2020-02-16 10:56:05
【问题描述】:

什么时候在try..except 块中使用finally 有意义? try..except 之后的列表语句不也是这样做的吗?

这两者有什么区别?

try:
    result = 100 / 0
except ZeroDivisionError:
    print("division by zero!")
else:
    print("result is", result)
finally:
    print("final statement")

对比

try:
    result = 100 / 0
except ZeroDivisionError:
    print("division by zero!")
else:
    print("result is", result)
print("final statement")

【问题讨论】:

    标签: python try-finally


    【解决方案1】:

    在 try.. 之后不是列出语句吗?除了做同样的事情吗?

    不,不是。您假设您已经涵盖了该块可以退出的所有方式。

    finally 保证被执行即使块被退出。这包括returncontinuebreak,不仅是例外。

    对于您的具体示例,您几乎覆盖了try 块之外的所有可能路径。但是你没有覆盖KeyboardInterruptMemoryError。如果有人在执行过程中点击了CTRL-C,那么只有第一个示例才会执行print("some code at last") 行。

    那是因为你的代码没有捕捉到KeyboardInterruptMemoryError,但这些异常仍然可能发生。如果为result = 100 / 0 语句引发了其中一个异常,则不会捕获该异常并且将退出整个帧。但不是在finally: 子句执行之前。

    用一个不同的例子来演示更容易,一个没有捕捉到异常的例子:

    mapping = {42: "The answer"}
    try:
        result = mapping[42] / 17
    except KeyError:
        print("Oops, no key 42 defined!")
    else:
        print(result)
    finally:
        del mapping
    

    这里,finally 语句被执行,即使上面引发了 TypeError 异常:

    >>> mapping = {42: "The answer"}
    >>> try:
    ...     result = mapping[42] / 17
    ... except KeyError:
    ...     print("Oops, no key 42 defined!")
    ... else:
    ...     print(result)
    ... finally:
    ...     del mapping
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    TypeError: unsupported operand type(s) for /: 'str' and 'int'
    >>> mapping  # was deleted in the `finally` block
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'mapping' is not defined
    

    这就是finally 通常的用途,清理资源。你甚至可以在 return 退出函数时使用它:

    >>> def foo():
    ...     try:
    ...         return 42
    ...     finally:
    ...         print("Returning doesn't stop finally from executing!")
    ...     print("This is never reached")
    ...
    >>> foo()
    Returning doesn't stop finally from executing!
    42
    

    请注意,Python 也有 with statementcontext managers 来帮助完成相同的工作。上下文管理器封装通常在 finally 中完成的清理工作,让您避免在较长的代码段末尾查找 finally 块来检查是否有文件已关闭。

    所以而不是:

    fileobj = open(filename)
    try:
        with line in fileobj:
            # many lines of parsing code
            # .
            # etc.
            # .
    finally:
        fileobj.close()
    

    您可以将文件对象用作上下文管理器,以上内容简化为:

    with open(filename) as fileobj:
        with line in fileobj:
            # many lines of parsing code
            # .
            # etc.
            # .
    

    【讨论】:

    • 感谢您如此详尽的回答!现在更清楚何时以及为什么使用finally 语句。
    猜你喜欢
    • 2015-12-06
    • 2022-01-04
    • 2011-02-21
    • 2013-05-18
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    相关资源
    最近更新 更多