ZetCode

Python 上下文管理器

最后修改于 2025 年 2 月 24 日

Python 中的上下文管理器用于管理文件句柄、数据库连接和锁等资源。它们确保资源即使在发生异常时也能被正确地获取和释放。本教程涵盖了上下文管理器的基础知识、它们与 with 语句的用法以及实际示例。

上下文管理器是定义代码块运行时上下文的对象。它们通常与 with 语句一起使用,以确保资源得到妥善管理。最常见的用例是文件处理,文件在代码块执行后会被自动关闭。

使用上下文管理器进行文件处理

此示例演示了如何使用上下文管理器处理文件操作。

file_handling.py
with open('example.txt', 'w') as file:
    file.write('Hello, World!')

with 语句确保文件在代码块执行后被正确关闭,即使发生异常。这消除了对显式 try-finally 块的需求。

自定义上下文管理器

此示例演示了如何使用类创建自定义上下文管理器。

custom_context_manager.py
class CustomContextManager:
    def __enter__(self):
        print("Entering the context")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("Exiting the context")
        if exc_type:
            print(f"An exception occurred: {exc_value}")

with CustomContextManager() as manager:
    print("Inside the context")

__enter__ 方法在进入上下文时被调用,__exit__ 方法在退出上下文时被调用。__exit__ 方法还处理在上下文中发生的任何异常。

使用 contextlib 的上下文管理器

此示例演示了如何使用 contextlib 模块创建上下文管理器。

contextlib_example.py
from contextlib import contextmanager

@contextmanager
def custom_context_manager():
    print("Entering the context")
    try:
        yield
    finally:
        print("Exiting the context")

with custom_context_manager():
    print("Inside the context")

contextmanager 装饰器用于从生成器函数创建上下文管理器。yield 语句分隔了设置和清理代码。

数据库连接管理

此示例演示了如何使用上下文管理器管理数据库连接。

database_connection.py
import sqlite3

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name

    def __enter__(self):
        self.conn = sqlite3.connect(self.db_name)
        return self.conn

    def __exit__(self, exc_type, exc_value, traceback):
        self.conn.close()

with DatabaseConnection('example.db') as conn:
    cursor = conn.cursor()
    cursor.execute('CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT)')

DatabaseConnection 类确保数据库连接在代码块执行后被正确关闭。这可以防止资源泄露并确保妥善清理。

锁管理

此示例演示了如何使用上下文管理器管理线程锁。

lock_management.py
import threading

lock = threading.Lock()

with lock:
    print("Lock acquired")
    # Critical section of code

with 语句确保锁在进入临界区之前被获取,并在退出后被释放,即使发生异常。

代码执行计时

此示例演示了如何使用上下文管理器来计时代码块的执行。

timing_execution.py
import time

class Timer:
    def __enter__(self):
        self.start_time = time.time()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.end_time = time.time()
        print(f"Execution time: {self.end_time - self.start_time} seconds")

with Timer():
    time.sleep(2)  # Simulate a time-consuming task

Timer 类测量 with 语句中代码块的执行时间。当退出代码块时,会打印经过的时间。

使用上下文管理器的最佳实践

来源

Python contextlib 文档

在本文中,我们探讨了 Python 上下文管理器,并通过实际示例演示了它们的使用。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出所有 Python 教程