ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Python 上下文管理器 with ~

Python 上下文管理器 with ~ 核心作用进入时做资源打开退出时自动执行清理shutdown/close就算抛异常也一定会执行不用手动写 try‑finally。1. 两种写法方式1直接使用现成支持 with 的对象日常最多很多库自带__enter__/__exit__直接套with# 文件退出自动closewithopen(test.txt,r,encodingutf‑8)asf:dataf.read()# 数据库连接、线程锁、http session 都是同理离开 with 代码块自动调用.close()发生异常也会关闭。方式2自己实现类的上下文管理器自定义自动 shutdown实现两个魔术方法__enter__进入with块时执行返回值给as 变量__exit__退出块时无论正常/异常都会执行做 shutdown、释放资源classMyClient:def__init__(self):passdefstart(self):启动连接print(启动连接)defshutdown(self):销毁、关闭资源print(执行 shutdown释放连接)def__enter__(self):self.start()returnself# 给到 with ... as objdef__exit__(self,exc_type,exc_val,exc_tb):# exc_type 不为None代表里面抛出了异常self.shutdown()# 返回 True吃掉异常返回False/None向外抛出异常returnFalse# 使用withMyClient()ascli:print(业务逻辑执行)# 哪怕这里抛异常也会自动走到 shutdown# raise ValueError(出错啦)# 出with块已经自动shutdown__exit__的三个参数异常类型、异常实例、堆栈。不需要处理异常直接忽略即可。方式3contextmanager装饰器写起来最简工程代码最常用不用写类用生成器函数yield之前是进入逻辑yield之后是退出/清理逻辑。⚠️ yield 后面的代码哪怕内部抛异常依然会执行非常适合做 shutdown。fromcontextlibimportcontextmanagercontextmanagerdefmy_resource():# enter 阶段打开资源 print(打开资源)try:yield资源对象# 这里产出的值给到 as 后面变量finally:# exit 阶段一定会执行shutdown/释放 print(自动执行 shutdown释放资源)# 调用withmy_resource()asres:print(f使用{res})# raise Exception(模拟报错)# 出with已经释放这是写工具、封装客户端最推荐的写法代码短。要点with本质就是语法糖等价手写try‑finallyobjMyClient()obj.__enter__()try:# 业务代码finally:obj.__exit__(...)__exit__/ finally 一定会跑但是不能保证进程被 os kill 的场景系统强杀进程Python 代码没机会执行清理。大模型/向量库场景常见把客户端、Milvus 连接、MinerU http session 包成上下文管理器出块自动关闭连接。极简对比总结写法适用场景直接 with 对象库已经实现好日常读写文件、锁、sessionclass __enter__/__exit__需要复杂类实例要维护大量成员属性contextmanager轻量封装只需要打开‑关闭逻辑工程最常用
返回列表