Python 中的上下文管理器进阶:基于生成器的简易实现

除了通过类实现上下文管理器(__enter__ 和 __exit__ 方法),Python 还允许使用 contextlib 模块的 contextmanager 装饰器,通过生成器快速定义上下文管理器。这种方式更简洁,适合简单场景的资源管理。

生成器上下文管理器的原理

使用 @contextmanager 装饰器的生成器函数,需包含一个 yield 语句:

  • yield 之前的代码等价于 __enter__ 方法(进入上下文时执行)
  • yield 之后的代码等价于 __exit__ 方法(退出上下文时执行,无论是否发生异常)
  • yield 的返回值会被 with 语句的 as 子句接收

示例:实现一个简易的文件操作上下文管理器

python

from contextlib import contextmanager

@contextmanager
def file_manager(file_path, mode):
    # 等价于 __enter__:获取资源
    file = open(file_path, mode)
    try:
        yield file  # 返回资源给 as 子句
    finally:
        # 等价于 __exit__:释放资源
        file.close()
        print("文件已关闭")

# 使用上下文管理器
with file_manager("test.txt", "w") as f:
    f.write("Hello, context manager!")

上述代码与 open 函数的内置上下文管理器功能一致,但实现更简洁。

应用场景与优势

临时资源管理:如临时文件、数据库连接、网络套接字等,确保使用后自动释放。

@contextmanager
def db_connection():
    conn = create_db_connection()  # 建立连接
    try:
        yield conn
    finally:
        conn.close()  # 确保关闭连接

环境变量临时修改:在代码块内临时修改环境变量,退出后自动恢复。

import os
from contextlib import contextmanager

@contextmanager
def temp_env_var(key, value):
    original = os.getenv(key)  # 保存原始值
    os.environ[key] = value
    try:
        yield
    finally:
        # 恢复原始值(若不存在则删除)
        if original is None:
            del os.environ[key]
        else:
            os.environ[key] = original

代码块计时:统计代码块执行时间,自动处理计时开始与结束。

与类实现相比,生成器上下文管理器的优势在于:代码量少、逻辑清晰,适合无需复杂状态管理的场景。

每天坚持学习一点点,不求有回报,只愿可以丰富自己!!!

© 版权声明

相关文章

1 条评论

none
暂无评论...