0Pricing
Python Academy · 课时

深入理解 with 语句

了解 with 的工作方式,以及它为何能防止资源泄漏。

深入理解 with 语句 是 CoddyKit 上的免费 Python Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

简介

with 语句可以确保设置和清理代码都会运行,即使发生异常也是如此。

with 的基本用法

with expr as var:expr 必须返回一个上下文管理器。var 会绑定到 __enter__ 返回的对象。
with open('/tmp/cm_test.txt','w') as f:
    f.write('hello')
print('file closed:', f.closed)

为什么需要 with

文件、锁和数据库连接等资源都必须释放。即使异常中断了代码块,with 也能确保完成清理。
# Without with:
# f = open('f.txt')
# try: ...
# finally: f.close()
# With with:
# with open('f.txt') as f: ...
print('with is cleaner')

多个上下文管理器

with open(a) as f, open(b) as g:可以在一条语句中打开两个资源。退出时两个资源都会被关闭。
import tempfile, os
a = tempfile.mktemp(); b = tempfile.mktemp()
with open(a,'w') as fa, open(b,'w') as fb:
    fa.write('A'); fb.write('B')
os.unlink(a); os.unlink(b)
print('both closed')

with 不会抑制异常

默认情况下,with 代码块中的异常会继续传播。__exit__ 可以通过返回 True 来抑制异常。
try:
    with open('/nonexistent.txt') as f:
        pass
except FileNotFoundError as e:
    print('caught:', e)

将 Lock 用作上下文管理器

threading.Lock() 可以作为上下文管理器使用:with lock:确保锁始终会被释放。
import threading
lock = threading.Lock()
with lock:
    print('locked section')
print('lock released')

数据库连接模式

将数据库连接用作上下文管理器时,成功后会提交,发生异常时会回滚——这是一个关键模式。
# Typical DB pattern:
# with db.transaction() as conn:
#     conn.execute(sql)
# commits on success, rolls back on exception
print('db pattern demo')

嵌套 with 语句

嵌套使用 with 语句完全没有问题。内部上下文管理器会先退出,然后外部上下文管理器退出。
import tempfile
tmp = tempfile.mktemp()
with open(tmp,'w') as outer:
    with open(tmp,'r+') as inner:
        outer.write('x')
import os; os.unlink(tmp)
print('nested exit order')

contextlib.suppress

contextlib.suppress(ExcType) 会在 with 代码块中静默忽略指定的异常类型。
from contextlib import suppress
with suppress(FileNotFoundError):
    open('/does/not/exist.txt')
print('no error raised')

contextlib.redirect_stdout

contextlib.redirect_stdout(f) 会暂时将 print() 的输出重定向到 f。
from contextlib import redirect_stdout
import io
buf = io.StringIO()
with redirect_stdout(buf):
    print('captured')
print('got:', buf.getvalue())

ExitStack

contextlib.ExitStack 可以管理数量动态变化的上下文管理器——当您不知道需要打开多少个文件时非常有用。
from contextlib import ExitStack
import tempfile, os
with ExitStack() as stack:
    files = [stack.enter_context(open(tempfile.mktemp(),'w')) for _ in range(3)]
    for f in files: f.write('x')
print('all closed')

快速检查

contextlib.suppress(FileNotFoundError) 会做什么?

回顾

with 会确保完成清理。一个 with 中可以有多个目标。contextlib.suppress 会静默忽略指定的错误。ExitStack 可以管理数量动态变化的上下文管理器。

继续学习

做得很好!下一课正等待您的学习。

常见问题解答

「深入理解 with 语句」课时是免费的吗?

是的 — 「深入理解 with 语句」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「深入理解 with 语句」这节课中我会学到什么?

了解 with 的工作方式,以及它为何能防止资源泄漏。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「深入理解 with 语句」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 深入理解 with 语句
  2. __enter__ 与 __exit__ 协议
  3. contextlib:@contextmanager
  4. 实用的上下文管理器模式
← 返回 Python Academy