目录:
contextlib 模块用于简化上下文管理器的创建和使用,让开发者能够更简洁、安全地管理资源(如文件、锁、数据库连接等),从而避免资源泄漏。
with 语句要求对象实现 __enter__() 和 __exit__() 方法,构成上下文管理器协议。
contextlib 可以简化这些方法。
with open('example.txt', 'w') as file:
file.write('Hello, World!')
可以将一个包含 yield 语句的生成器函数直接转换为上下文管理器,无需定义类。
yield 语句之前的代码相当于 __enter__(),用于获取和设置资源;yield 语句返回的值会绑定到 as 子句的变量;yield 语句之后的代码(通常放在 finally 块中)相当于 __exit__(),用于确保资源释放。
示例: 文件操作
from contextlib import contextmanager
@contextmanager
def managed_file(filename, mode='r'):
f = open(filename, mode)
try:
yield f # 将打开的文件对象提供给 with 代码块使用
finally:
f.close() # 无论 with 块中是否发生异常,文件都会被关闭
# 使用方式
with managed_file('data.txt') as file:
data = file.read()
print(data)
示例: 数据库连接
import sqlite3
from contextlib import contextmanager
@contextmanager
def get_db(db_path):
conn = sqlite3.connect(db_path)
try:
yield conn # 提供连接给 with 代码块
conn.commit() # 如果没有异常,提交事务
except Exception:
conn.rollback() # 如果发生异常,回滚事务
raise # 重新引发异常,这是关键!否则 with 语句会认为异常已被处理[1](@ref)
finally:
conn.close() # 最终确保连接关闭
with get_db('app.db') as conn:
cursor = conn.cursor()
cursor.execute("INSERT INTO logs (message) VALUES ('test entry')")
示例: 性能计时器。上下文管理器不限于“打开-关闭”,任何“进入时做A,离开时做B”的模式都适用
import time
from contextlib import contextmanager
@contextmanager
def timer(name):
start = time.time()
print(f"{name} 开始...")
yield # 这里不需要提供值给 as
elapsed = time.time() - start
print(f"{name} 完成,耗时 {elapsed:.2f} 秒")
with timer("数据清洗流程"):
# 模拟耗时操作
data = [i**2 for i in range(1000000)]
↶ 返回首页 ↶