ZetCode

Python With 语句

最后修改于 2025 年 2 月 25 日

Python 中的 with 语句通过确保正确的设置和清理来简化资源管理。它与上下文管理器一起工作,以处理异常并自动释放资源。本教程涵盖 with 关键字、上下文管理器和实际应用。

with 语句将代码执行包装在上下文管理器定义的方法中。它保证资源(如文件或网络连接)被正确初始化和清理,即使在处理过程中发生错误也是如此。

基本文件处理

此示例演示了如何使用 with 语句读取文件。该文件在代码块执行后自动关闭。

read_file.py
with open('data.txt', 'r') as file:
    content = file.read()
    print(content[:50])  # Print first 50 characters

# File is closed automatically here

open 函数返回一个文件对象,该对象充当上下文管理器。在代码块完成后,文件的 __exit__ 方法会关闭资源,即使发生异常也是如此。

自定义上下文管理器类

此示例使用带有 __enter____exit__ 方法的类创建一个自定义上下文管理器。

custom_context.py
class DatabaseConnection:
    def __enter__(self):
        print("Establishing connection")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Closing connection")
    
    def query(self):
        print("Executing query")

with DatabaseConnection() as conn:
    conn.query()

# Output:
# Establishing connection
# Executing query
# Closing connection

__exit__ 方法总是在代码块之后执行,确保资源清理。这种模式对于管理数据库连接或网络套接字很有用。

使用 contextlib 处理生成器

此示例使用 contextlib.contextmanager 从生成器函数创建一个上下文管理器。

generator_context.py
from contextlib import contextmanager

@contextmanager
def timer():
    import time
    start = time.time()
    yield
    print(f"Elapsed: {time.time() - start:.2f}s")

with timer():
    data = [x**2 for x in range(1000000)]

@contextmanager 装饰器将生成器转换为上下文管理器。 yield 之前的代码在进入时运行,之后的代码在退出时运行。

处理多个资源

with 语句可以同时管理多个上下文管理器。

multiple_resources.py
with open('input.txt', 'r') as src, open('output.txt', 'w') as dest:
    content = src.read()
    dest.write(content.upper())

print("Files processed and closed")

这两个文件在代码块之后自动关闭。 这种方法确保所有资源都被释放,即使在处理过程中发生错误也是如此。

With 块中的错误处理

此示例显示了 with 语句如何在访问资源时处理异常。

error_handling.py
try:
    with open('missing.txt', 'r') as file:
        print(file.read())
except FileNotFoundError:
    print("Error: File not found")

with 语句确保在处理异常之前关闭文件。 上下文管理器处理清理,无论成功还是失败。

With 语句的最佳实践

来源

Python With 语句文档

在本文中,我们探讨了 Python with 语句,并通过实际示例演示了它在资源管理中的使用。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直撰写编程文章。 到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程