You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中是否存在适用于类的contextlib.contextmanager版本?

用生成器定义类上下文管理器的实现方案

完全可以实现,不需要改变原有类实例化加with块的使用模式,也不需要修改__init__的原有逻辑,最常用的实现方式是在类内部封装一个被@contextlib.contextmanager装饰的生成器方法,再把__enter__和__exit__的逻辑透传给这个生成器上下文管理器即可。

实现示例

import contextlib

class Client:
    def __init__(self, host: str, port: int):
        # __init__ 中正常编写初始化逻辑,比如参数存储、预校验等
        self.host = host
        self.port = port
        # 初始化内部的上下文管理器实例
        self._inner_cm = self._gen_context()

    @contextlib.contextmanager
    def _gen_context(self):
        # 此处编写上下文进入时的逻辑,比如建立连接、申请资源
        self.connection = self._build_connection()
        try:
            # yield 返回的对象就是 with 块中 as 后拿到的实例,这里返回类自身即可
            yield self
        except Exception as e:
            # 此处编写异常处理逻辑
            self._handle_exception(e)
            # 不需要上层捕获异常可返回 True,需要向上抛出就执行 raise
            raise
        finally:
            # 此处编写退出时的清理逻辑,比如关闭连接、释放资源
            self.connection.close()

    def __enter__(self):
        return self._inner_cm.__enter__()

    def __exit__(self, exc_type, exc_val, exc_tb):
        return self._inner_cm.__exit__(exc_type, exc_val, exc_tb)

    # 以下为类的业务方法示例
    def _build_connection(self):
        print(f"建立到 {self.host}:{self.port} 的连接")
        return object()

    def _handle_exception(self, e: Exception):
        print(f"捕获到异常: {str(e)}")

    def blah(self):
        print("执行 Client 类的 blah 方法")

使用方式

和常规的类上下文管理器使用模式完全一致,不需要做任何改动:

with Client("127.0.0.1", 8080) as c:
    c.blah()

注意事项

  • 这种实现的语法和独立上下文管理器的写法完全一致,没有额外学习成本,所有状态都统一在生成器方法中管理,逻辑清晰不易出错。
  • 生成器的额外开销极低,和手写__enter__、__exit__方法的性能几乎没有差异。
  • 上述方案兼容Python 3.5及以上的绝大多数生产环境版本,无特殊依赖。

内容的提问来源于stack exchange,提问作者Att Righ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:54:00