实用的上下文管理器模式
将上下文管理器应用于文件、锁、计时器和 DB 连接。
实用的上下文管理器模式 是 CoddyKit 上的免费 Python Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
简介
上下文管理器能够优雅地解决文件、数据库、锁、计时器等场景中的实际资源管理问题。
文件处理流程
同时打开输入和输出文件,逐行处理,并自动关闭二者。
import io
src = io.StringIO('line1\nline2\nline3')
dst = io.StringIO()
with src, dst:
for line in src:
dst.write(line.upper())
print(dst.getvalue())数据库事务
将数据库操作包装在 CM 中:成功时提交,发生异常时回滚,并始终关闭。
from contextlib import contextmanager
@contextmanager
def db_transaction(conn):
try:
yield conn
print('COMMIT')
except Exception as e:
print(f'ROLLBACK: {e}')
raise
finally:
print('CLOSE')
with db_transaction({'execute': lambda q: print(f'SQL: {q}')}) as db:
db['execute']('INSERT ...')线程锁
使用锁时会获取锁、执行主体,并在退出时释放锁——无需手动获取或释放。
import threading
lock = threading.Lock()
shared = []
def add(x):
with lock:
shared.append(x)
add(1); add(2)
print(shared)切换目录
os.chdir() 会全局更改工作目录。CM 会保存并恢复工作目录。
from contextlib import contextmanager
import os
@contextmanager
def chdir(path):
old = os.getcwd()
os.chdir(path)
try: yield
finally: os.chdir(old)
original = os.getcwd()
with chdir('/tmp'):
print('in tmp:', os.getcwd())
print('back:', os.getcwd())临时文件
tempfile.NamedTemporaryFile 作为 CM 会自动创建并删除临时文件。
import tempfile
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=True) as f:
f.write('temp data')
print('temp file:', f.name)
print('deleted')环境变量修改
为测试或子进程临时设置环境变量,然后将其恢复。
from contextlib import contextmanager
import os
@contextmanager
def env(**kwargs):
old = {k: os.environ.get(k) for k in kwargs}
os.environ.update({k:str(v) for k,v in kwargs.items()})
try: yield
finally:
for k,v in old.items():
if v is None: os.environ.pop(k,None)
else: os.environ[k]=v
with env(DEBUG='1', LOG_LEVEL='DEBUG'):
print(os.environ['DEBUG'])性能分析代码块
在 CM 中使用 cProfile 包装代码块,以测量其性能。
from contextlib import contextmanager
import cProfile
@contextmanager
def profile():
pr = cProfile.Profile()
pr.enable()
yield pr
pr.disable()
with profile() as pr:
sum(range(1000000))
print('profiled')网络套接字
套接字实现了 CM 协议:使用 with socket.socket() as s: 会在退出时关闭套接字。
import socket
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.1)
print('socket ready')
except Exception as e:
print(f'socket: {e}')捕获警告
warnings.catch_warnings() 会捕获代码块内部发出的警告,在测试中很有用。
import warnings
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
warnings.warn('test warning')
print(len(w), w[0].category.__name__)组合模式
实际项目中的 CM 经常会组合多种模式:在一个可复用组件中同时处理事务、日志记录和计时。
from contextlib import contextmanager
import time
@contextmanager
def timed_operation(name):
print(f'[{name}] start')
t0 = time.perf_counter()
try:
yield
print(f'[{name}] done in {time.perf_counter()-t0:.4f}s')
except Exception as e:
print(f'[{name}] failed: {e}')
raise
with timed_operation('loop'):
sum(range(100000))快速检查
哪种线程原语实现了上下文管理器协议,可确保并发访问安全?
总结
上下文管理器模式包括:文件处理流程、数据库事务、锁、目录切换、临时文件、环境变量修改和性能分析。对于动态资源栈,请使用 ExitStack。
继续学习
做得很好!下一课正在等待您。
常见问题解答
「实用的上下文管理器模式」课时是免费的吗?
是的 — 「实用的上下文管理器模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「实用的上下文管理器模式」这节课中我会学到什么?
将上下文管理器应用于文件、锁、计时器和 DB 连接。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「实用的上下文管理器模式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。