上下文管理器的作用
with语句简化了资源管理,能自动处理资源的获取和释放。很多文件操作都适合使用with语句。
# 传统方式
file = open('test.txt', 'r')
try:
content = file.read()
finally:
file.close()
# with语句方式
with open('test.txt', 'r') as file:
content = file.read()
with语句基本语法
掌握with语句的核心用法。
with expression as variable:
# 代码块
pass
# 多个资源管理
with open('input.txt') as infile, open('output.txt', 'w') as outfile:
content = infile.read()
outfile.write(content)
自定义上下文管理器
实现__enter__和__exit__方法。
classMyContextManager:
def__enter__(self):
print("进入上下文")
return self
def__exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
returnFalse# 不处理异常
with MyContextManager() as cm:
print("在上下文中")
处理异常的上下文管理器
在__exit__中处理异常。
classSafeFile:
def__init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def__enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def__exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# 返回True表示已处理异常
if exc_type isnotNone:
print(f"发生异常: {exc_val}")
returnTrue
contextlib模块实战
使用contextlib简化上下文管理器。
from contextlib import contextmanager
@contextmanager
defmanaged_file(filename, mode):
file = open(filename, mode)
try:
yield file
finally:
file.close()
with managed_file('test.txt', 'r') as f:
content = f.read()
上下文管理器链
多个上下文管理器可以叠加使用。
from contextlib import nested
with nested(open('a.txt'), open('b.txt')) as (f1, f2):
content1 = f1.read()
content2 = f2.read()
实战案例:数据库连接管理
用上下文管理器管理数据库连接。
classDatabaseConnection:
def__init__(self, db_url):
self.db_url = db_url
self.connection = None
def__enter__(self):
self.connection = create_engine(self.db_url).connect()
return self.connection
def__exit__(self, exc_type, exc_val, exc_tb):
if self.connection:
self.connection.close()
with DatabaseConnection('sqlite:///test.db') as conn:
result = conn.execute('SELECT * FROM users')
实战案例:临时目录管理
使用tempfile模块创建临时目录。
import tempfile
import os
with tempfile.TemporaryDirectory() as tmpdir:
temp_file = os.path.join(tmpdir, 'temp.txt')
with open(temp_file, 'w') as f:
f.write('临时内容')
# 退出后临时目录自动删除
contextlib的其他用法
contextlib提供的便捷工具。
from contextlib import suppress, redirect_stdout
# 忽略特定异常
with suppress(FileNotFoundError):
os.remove('nonexistent.txt')
# 重定向输出
with open('output.txt', 'w') as f:
with redirect_stdout(f):
print("输出到文件")