上下文管理器是一个定义 setup 和 teardown 逻辑的对象,与 with 语句一起使用。它保证清理操作(关闭文件、释放锁、回滚事务)自动发生 — 即使发生错误。
它解决的问题
python
f = ()
data = f.read()
process(data)
f.close()
() f:
data = f.read()
process(data)
with 块确保当块退出时(无论是正常还是通过异常)f.close() 都会运行 — 消除了遗忘或跳过清理导致的资源泄漏。
with open("f.txt") as f: ... # files (auto-close)
with lock: # threading locks (auto-release)
shared_resource += 1
with db.transaction(): # DB transactions (auto-commit/rollback)
...
with open("a") as a, open("b") as b: # multiple at once
...
class Timer:
def __enter__(self): # SETUP — runs at `with` entry
self.start = time.perf_counter()
return self # the value bound to `as`
def __exit__(self, exc_type, exc_val, tb): # TEARDOWN — runs at exit (even on error)
print(f"took {time.perf_counter() - self.start:.3f}s")
# return False → propagate any exception; True → suppress it
with Timer():
do_work()
上下文管理器实现 __enter__(setup)和 __exit__(cleanup,接收任何异常信息)。
from contextlib import contextmanager
@contextmanager
def timer():
start = time.perf_counter()
try:
yield # everything before yield = setup; after = teardown
finally:
print(f"took {time.perf_counter() - start:.3f}s")
with timer():
do_work()
@contextmanager 装饰器将生成器转变为上下文管理器 — yield 之前是 setup,之后是 cleanup(为安全起见在 finally 中)。
上下文管理器和 with 是安全处理资源管理的 Pythonic 方式 — 保证文件被关闭、锁被释放、连接被返回、事务被完成,即使发生异常。
这防止了资源泄漏和不一致的状态,这是手动清理中常见的 bug 来源。
它们被广泛使用(每个文件操作都应该使用 with),知道如何编写自己的上下文管理器(通过 __enter__/__exit__ 或更简单的 @contextmanager)让你能以干净且可靠的方式封装任何 setup/teardown 模式。