上下文管理器
1. 上下文管理器
一个类如果实现了__enter()__和__exit()___两个魔法方法,该类创建的对象我们称为上下文管理器。
对于上下文管理器我们可以使用with语句。进入with语句会调用上下文管理器的__enter__(),离开with语句作用域时会自动调用上下文管理器的__exit()__。
py
class File(object):
def __init__(self, file_name, open_mode):
self.__file_name = file_name
self.__open_mode = open_mode
def __enter__(self):
self.__file = open(self.__file_name, self.__open_mode)
return self.__file
def __exit__(self, exc_type, exc_val, exc_tb):
self.__file.close()
if __name__ == '__main__':
# with语句使用上下文管理器
with File("test.txt", "w") as file:
# w模式不允许读取文件。操作出错,离开with语句时依然会执行__exit__()方法关闭文件
content = file.read()
print(content)with语句必须配合上下文管理器使用。上下文管理可以实现try...finally...的效果,它提供了一种简单且安全的方式来使用需要及时关闭和释放的资源。
with和上下文管理器的搭配非常类似于.Net中using和IDisposable的组合来使用和释放非托管资源,而using方式使用IDisposable对象本质就是使用了try...finally...结构,在finally语句中调用对象的Close和Dispose方法。
2. contextmanager
上下文管理器除了上述使用方式之外,还提供了一个contextmanager装饰器配合yield生成器来简化上下文管理器的使用。
yield之前的内容在__enter()__中执行,yield之后的内容在__exit()__中执行。yield后面的值作为__enter()__返回值。
py
from contextlib import contextmanager
@contextmanager
def file(file_name, open_mode):
_file = open(file_name, open_mode) # yield前 在__enter__()中执行
yield _file
_file.close() # yield后 在__exit__()中执行
if __name__ == '__main__':
with file("test.txt", "w") as f:
content = f.read()
print(content)