引入:
打开一个文件并写入‘hello, world’,可用代码一和代码二实现:
代码一:
f = open("hello.txt", 'w')
try:
f.write('hello, world')
finally:
f.close()
代码二:
with语句通过在上下文管理器中封装try…finally语句的标准用法来简化异常处理
with open('hello.txt', 'w') as f:
f.write('hello, world')
如何在自定义的对象(类和函数)中支持with?
自定义对象实现上下文管理器即可
上下文管理器是一个简单的协议(接口),自定义的对象需要遵循这个接口来支持with语句。具体做法,向自定义对象中添加__enter__和__exit__方法,Python将在资源管理的适当时间调用这两种方法。
实际代码,内置open()函数上下文管理器的一个简单实现
基于类实现
class ManagedFile:
def __init__(self, name):
self.name = name
def __enter__(self):
self.file = open(self.name, 'w')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
其中ManagedFile类也遵循上下文管理器协议,与原open()一样也支持with语句
with ManagedFile('hello.txt') as f:
f.write('hello, world')
进入with语句上下文,Python调用__enter__获取资源,离开with语句上下文,Python调用__exit__释放资源。
基于生成器实现
利用标准库contextlib模块的contextmanager装饰器重写之前的ManagedFile上下文管理器
from contextlib import contextmanager
@contextmanager
def managed_file(name):
try:
f = open(name, 'w')
yield f
finally:
f.close()
with managed_file('hello.txt') as f:
f.write('hello, world')
小结:with语句有助于简化一些通用资源管理模式,抽象出其中的功能,将其分解并重用
参考书籍:Python Tricks