Administrator
Published on 2025-03-14 / 5 Visits
0
0

Python @contextmanager 装饰器原理详解

Python 的 @contextmanager 装饰器(来自 contextlib 模块)通过生成器简化了上下文管理器的创建。它的核心原理是将生成器的 yield 语句拆分为 __enter____exit__ 两个阶段,最终生成一个符合上下文协议的对象。


核心步骤

  1. 生成器分段

    • yield 前的代码对应 __enter__ 逻辑(资源分配)。
    • yield 后的代码对应 __exit__ 逻辑(资源清理)。
  2. 装饰器魔法

    from contextlib import contextmanager
    
    @contextmanager
    def my_context():
        print("Enter")  # __enter__ 阶段
        yield "资源"     # 暂停,返回资源
        print("Exit")   # __exit__ 阶段
    
  3. 执行流程

    with my_context() as res:
        print("Using", res)
    
    # 输出:
    # Enter
    # Using 资源
    # Exit
    

等价于类实现

@contextmanager 生成的上下文管理器等价于:

class MyContext:
    def __enter__(self):
        print("Enter")
        return "资源"
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exit")
        return False  # 不抑制异常

异常处理

装饰器自动处理异常传播:

  • yield 后的代码会在 __exit__ 中执行,无论 with 块是否抛出异常。
  • 若需捕获异常,可在生成器中使用 try...finally
    @contextmanager
    def safe_open():
        resource = acquire_resource()
        try:
            yield resource
        finally:
            release_resource(resource)  # 确保资源释放
    

关键优势

  • 代码简洁:无需手动实现 __enter__/__exit__
  • 逻辑直观:用线性代码表达资源生命周期。
  • 轻量级:适合快速创建一次性上下文管理器。

理解这一机制后,可以更灵活地利用生成器控制资源管理边界。


Comment