Python finally 子句

在处理 Python 异常 时,如果希望代码块不管有没有发生异常,都继续执行某些语句,我们可以使用 finally 子句来实现。

语法:

try:
    ……
except Exception as reason:
    ……
finally:
    ……

示例:finally 子句的基本用法

f = None
try:
    f = open(r'data\A.txt', 'r', encoding='utf-8')
    result = f.read() + 1000
    f.close()
except TypeError as reason:
    print(reason)

运行结果如下。

(报错)TypeError: can only concatenate str (not 'int') to str

分析:

在上面示例中,程序从上到下执行,但是执行到 result = f.read() + 1000 这一句代码时就会发生异常,后面的 f.close() 就不会执行了。此时文件已经被打开了,却没有被关闭,这不符合预期。

如果希望不管 try except 代码块中是否发生异常,我们都要执行 f.close() 关闭文件,就可以使用 finally 子句来实现,代码如下:

f = None
try:
    f = open(r'data\A.txt', 'r', encoding='utf-8')
    result = f.read() + 1000
except TypeError as reason:
    print(reason)
finally:
    if f:      # 只有当f成功被赋值(即文件成功打开)时才尝试关闭
        f.close()

对于 try...except...finally 语句,如果 try 语句块中没有发生任何异常,则会跳过 except 语句块,然后执行 finally 语句块。如果 try 语句块中发生异常,则会先执行 except 语句块,再执行 finally 语句块。也就是说,finally 语句块是无论是否发生异常,都一定会被执行的内容。异常处理的流程如下图所示。

Python finally 子句

异常是一个类,捕获异常就是捕获类的实例。前面介绍的都是用于处理 Python 内置的异常,实际上我们还可以自定义异常类。如果要抛出异常,可以根据需要定义一个异常类,然后使用 raise 语句抛出异常类的实例。

需要清楚的是,只有在必要的时候才去自定义一个异常类。平常开发时我们应该尽量使用 Python 内置的异常类(如 NameError、TypeError 等)。因此对于初学者而言,你并不需要过多关注自定义异常类以及 raise 语句。

提示: 如果在实际项目中要忽略某类异常,可以使用标准库模块 contextlib 里的 suppress 函数,它提供了现成的 “忽略异常” 功能。

最后总结一下 Python 异常处理,主要有以下 3 点。

  • except 语句可以有多个,Python 会按照顺序执行。如果异常已经被处理,后面的 except 就不会被执行了。
  • except 语句可以用元组的形式同时指定多个异常。
  • except 语句后面如果不指定异常,则表示捕获所有异常。

finally 子句与 with 语句之间的关系

在前面的章节中,我们强烈推荐使用 with open(...) as f: 来操作文件,这是因为它会自动帮我们关闭文件。

现在小伙伴们学完了 finally 子句,是不是明白了点什么呢?没错!with 语句 的底层原理,其实就是帮我们自动封装了 try...finally 的逻辑!

因此在操作文件时,虽然 finally 能完美胜任,但我们依然更推荐极其简洁的 with 语句。而在释放网络连接、清理数据库连接等其他复杂场景中,finally 才是真正的幕后英雄!

上一篇: Python else 子句

下一篇: Python assert

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号