Python3 with¶
概念与用途¶
with 通过上下文管理器在进入和离开代码块时执行配套操作,即使发生异常也能清理资源。文件、锁、数据库事务和临时目录都适合这一模式。
核心语法与 API¶
上下文管理器实现 __enter__ 与 __exit__,也可用 contextlib.contextmanager 和 yield 创建。多个资源可以写在同一条 with 中。
from contextlib import contextmanager
@contextmanager
def managed_message(name: str):
print("打开", name)
try:
yield name.upper()
finally:
print("关闭", name)
with managed_message("demo") as value:
print(value)
协议与工具¶
| 方式 | 适用对象 | 特点 |
|---|---|---|
__enter__/__exit__ |
类管理器 | 可复用复杂状态 |
@contextmanager |
单次进入/清理流程 | 简洁生成器写法 |
ExitStack |
动态数量资源 | 统一逆序释放 |
nullcontext |
可选管理器 | 消除分支重复 |
示例:动态打开多个资源¶
from contextlib import ExitStack
from io import StringIO
sources = ["first", "second", "third"]
with ExitStack() as stack:
streams = [stack.enter_context(StringIO(text)) for text in sources]
print([stream.read() for stream in streams])
ExitStack 按注册的反方向清理,适合资源数量运行时才确定的场景。进入过程中某个资源失败时,已经成功进入的资源仍会被释放。
常见错误与工程注意¶
- 不要依赖垃圾回收及时关闭文件、连接或锁。
__exit__返回真值会压制异常,除非明确需要,否则应让异常传播。- 不要在离开
with open(...)后继续使用已关闭的文件对象。