contextlib:@contextmanager
使用 contextlib 装饰器简洁地创建上下文管理器。
contextlib:@contextmanager 是 CoddyKit 上的免费 Python Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
为什么使用 contextlib?
contextlib.contextmanager 允许您将上下文管理器写成生成器函数,而不是类,从而减少样板代码。
from contextlib import contextmanager
@contextmanager
def managed():
print("setup")
yield
print("teardown")
with managed():
print("inside")生成值
您 yield 的任何值,都会绑定到 with 语句中的 as 变量。
from contextlib import contextmanager
@contextmanager
def temp_list():
lst = []
yield lst
print(f"Final list: {lst}")
with temp_list() as lst:
lst.append(1)
lst.append(2)@contextmanager 中的异常处理
请将 yield 放在 try/finally 中,以确保即使发生异常也能完成清理。
from contextlib import contextmanager
@contextmanager
def safe_open(path):
f = open(path)
try:
yield f
finally:
f.close()
with safe_open("data.txt") as f:
print(f.read())抑制异常
在生成器内部捕获异常即可抑制它——这与从 __exit__ 返回 True 相同。
from contextlib import contextmanager
@contextmanager
def ignore_value_errors():
try:
yield
except ValueError:
pass
with ignore_value_errors():
raise ValueError("ignored")contextlib.suppress
contextlib.suppress(*exceptions) 是一个现成的上下文管理器,可抑制指定的异常类型。
from contextlib import suppress
with suppress(FileNotFoundError):
open("missing.txt")
print("continues")contextlib.closing
closing(obj) 会创建一个上下文管理器,在退出时调用 obj.close()。它适用于具有 close() 但没有 __exit__ 的对象。
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen("https://example.com")) as page:
content = page.read()contextlib.nullcontext
nullcontext 是一个不执行任何操作的上下文管理器。当上下文管理器是可选项时很有用。
from contextlib import nullcontext
def process(data, lock=None):
cm = lock if lock is not None else nullcontext()
with cm:
return [x*2 for x in data]contextlib.ExitStack
ExitStack 允许您动态管理数量可变的上下文管理器。
from contextlib import ExitStack
files = ["a.txt", "b.txt", "c.txt"]
with ExitStack() as stack:
handles = [stack.enter_context(open(f)) for f in files]
data = [h.read() for h in handles]重复使用 @contextmanager
基于生成器的上下文管理器每次调用只能使用一次。要重复使用它,请再次调用经过装饰的函数。
from contextlib import contextmanager
@contextmanager
def counter():
count = 0
yield lambda: count.__add__ # each call is independent
print("done")
with counter():
pass
with counter():
passasynccontextmanager
对于异步代码,请使用 contextlib.asynccontextmanager,将 async with 管理器写成生成器。
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_session():
session = await create_session()
try:
yield session
finally:
await session.close()contextlib.redirect_stdout
将标准输出临时重定向到任意类似文件的对象。
import io
from contextlib import redirect_stdout
buf = io.StringIO()
with redirect_stdout(buf):
print("captured")
print(buf.getvalue()) # captured快速检查
在 @contextmanager 生成器中,应将清理代码放在哪里,才能确保即使发生异常也会执行?
总结
@contextmanager 会将生成器转换为上下文管理器。请在 yield 周围使用 try/finally 来安全地完成清理。contextlib 模块还提供 suppress、nullcontext、ExitStack 等工具。
常见问题解答
「contextlib:@contextmanager」课时是免费的吗?
是的 — 「contextlib:@contextmanager」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「contextlib:@contextmanager」这节课中我会学到什么?
使用 contextlib 装饰器简洁地创建上下文管理器。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「contextlib:@contextmanager」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 深入理解 with 语句
- __enter__ 与 __exit__ 协议
- contextlib:@contextmanager
- 实用的上下文管理器模式