Python3 with
Python3 学习笔记 · 整理自菜鸟教程
一句话
with 是上下文管理器语法,进入代码块自动分配资源、离开时(即使报错)自动释放,最常见的就是自动关闭文件。
要点
with保证资源必然被释放,比手写try/finally更短更安全。- 文件、锁、网络连接、数据库连接都支持
with。 - 一个
with语句可同时管理多个资源,用逗号分隔。 - 背后的协议:对象实现
__enter__()(进入)和__exit__()(退出)。 - 一旦
with是语言级协议,自定义类实现这两个方法即可支持with。 __exit__返回True会吞掉异常,返回False(或None)则异常继续抛出。contextlib提供了@contextmanager、closing、suppress等工具简化写法。
语法 / 常用方法
| 语法/方法 | 说明 | 示例 |
|---|---|---|
with expr as x: |
进入上下文,值绑定到 x | with open("f") as f: |
with a as x, b as y: |
同时管理多个资源 | with open(a) as fa, open(b) as fb: |
__enter__(self) |
进入时调用,返回值给 as |
return self.fp |
__exit__(self, et, ev, tb) |
退出时调用,负责清理 | self.fp.close() |
@contextmanager |
用生成器写上下文管理器 | 需 from contextlib import contextmanager |
contextlib.suppress(E) |
忽略指定异常 | with suppress(FileNotFoundError): |
contextlib.closing(obj) |
退出时调 obj.close() |
with closing(resp): |
代码示例
1 | |
易错点
with绑定的变量在块外仍可见(Python 无块级作用域),但资源已释放,别再用。- 忘了
as变量时写with open("f"):也能用,但拿不到文件对象。 __exit__返回值为真值才会吞异常,别误以为一定能捕获。@contextmanager里必须try/finally包住yield,否则中途异常跳过清理。with打开文件后,块外使用f.read()会ValueError: I/O operation on closed file。- 多个资源用逗号分隔时注意换行与反斜杠,别漏写
as。