with 语句

Python SELF ZH
第 21 级 , 课程 3
可用

4.1 文件关闭和错误处理

有时候在读取文件时会出错或者抛出异常,而文件却没有被关闭。这可能导致内存泄漏或者 file handler泄漏。因此文件操作需要放在try-except块中。

假设你有以下代码:


file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
file.close()  # 关闭文件

需要把它放在try-except块中:


try:
    file = open('example.txt', 'a')  # 打开文件
    file.write("This is a new line added to the file.")
    file.close()  # 关闭文件
except FileNotFoundError:
    print("File not found")
    file.close()  # 关闭文件

为了不多次调用close()方法,可以将其放在finally块中:


try:
    file = open('example.txt', 'a')  # 打开文件
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # 关闭文件

这个代码看起来不错,但……不工作,因为变量file只在try块中定义,在exceptfinally块中不可用。

所以我们需要把变量定义在更高的层级:


file = None
try:
    file = open('example.txt', 'a')  # 打开文件
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # 关闭文件

这个解决方案更好,但也有缺点。比如,如果文件无法打开,变量file将保持None。而关闭文件的尝试会引发错误——企图对不存在的对象调用close()方法。

因此需要在调用close()方法前增加检查:


file = None
try:
    file = open('example.txt', 'a')  # 打开文件
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    if file:
        file.close()  # 关闭文件

如果你惊讶于3行代码变成了9行,你并不孤单。幸运的是,已有解决方案,我们接下来会谈论。

4.2 with 语句

Python中的with语句提供了一种便捷的资源管理方式,比如文件,确保在with块结束后自动关闭。这样简化了代码,防止了资源泄漏,比如未关闭的文件。

with语句的一般语法:


with 表达式 as 变量:
    操作变量

with 语句用于 给代码块包装一个上下文管理器。使用with时,Python自动调用上下文管理器对象的__enter__()__exit__()方法,这简化了 资源管理。

使用with进行文件操作的示例:


with open('example.txt', 'w') as file:
    file.write("Hello, World!\n")
    file.write("This is a test file.\n")

在这个例子中,文件example.txt以写入模式打开,文件名绑定到变量filewith中的代码块 在完成所有写操作后会自动关闭文件。

4.3 自动关闭文件

使用with语句的一个主要优势是 在代码块结束后自动关闭文件。即使在发生异常时也会关闭文件,这使得代码更安全可靠。

自动关闭文件示例:


try:
    with open('example.txt', 'w') as file:
        file.write("Hello, World!\n")
        file.write("This is a test file.\n")
        # 抛出异常,检查文件是否仍然会被关闭
        raise Exception("Something went wrong")
except Exception as e:
    print(f"Caught an exception: {e}")
# 在这里文件已经关闭

操作文件时一定要使用with语句。这简单且能避免许多错误。

4.4 with语句的内在机制

with语句的根本在于__enter__()__exit__()方法,使用作为上下文管理器的类必须实现这些方法。

要让对象能用在with语句中,它必须实现__enter__()__exit__()方法。这些方法定义了进入和退出上下文时的行为。

__enter__() 方法

__enter__()方法在进入with时调用。 它初始化资源并返回将绑定到as后指定的变量的对象。

__exit__() 方法

__exit__()方法在退出with块时调用。它进行结束操作,比如释放资源或关闭文件。该方法接受三个参数:exc_typeexc_valexc_tb,这些参数包含异常信息(如果发生异常)。

  • exc_type:异常类型(例如, ZeroDivisionError)。
  • exc_val:异常值(例如, 错误信息)。
  • exc_tb:异常的堆栈跟踪。

如果__exit__()方法返回True, 则异常将被抑制。如果返回 False,异常将被重新抛出。

示例:


class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print(f"An exception occurred: {exc_type}, {exc_val}")
        return False  # 异常不被抑制
        
with MyContextManager() as manager:
    print("Inside the with block")
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION