from contextlib import contextmanager
@contextmanager
def open_managed_file(filename):
f = open(filename, 'w')
try:
yield f
finally:
f.close()
with open_managed_file('notes.txt') as f:
f.write('some todo...')
生成器首先获取资源。 然后,它暂时挂起其自己的执行并 产生 资源,以便调用者可以使用它。 当调用者离开 with 上下文时,生成器继续执行并释放 finally 语句中的资源。
上下文管理器是资源管理的绝佳工具。 它们使你可以在需要时精确地分配和释放资源。 一个著名的例子是
with open()
语句:这将打开一个文件,并确保在程序执行离开with语句的上下文之后自动将其关闭。 它还处理异常,并确保即使在发生异常的情况下也能正确关闭文件。 在内部,上面的代码翻译成这样的东西:
我们可以看到,使用上下文管理器和
with
语句更短,更简洁。上下文管理器示例
将上下文管理器实现为类
为了支持我们自己的类的
with
语句,我们必须实现__enter__
和__exit__
方法。 当执行进入with
语句的上下文时,Python调用__enter__
。 在这里,应该获取资源并将其返回。 当执行再次离开上下文时,将调用__exit__
并释放资源。处理异常
如果发生异常,Python将类型,值和回溯传递给
__exit__
方法。 它可以在这里处理异常。 如果__exit__
方法返回的不是True
,则with
语句将引发异常。我们可以在
__exit__
方法中处理异常并返回True
。将上下文管理器实现为生成器
除了编写类,我们还可以编写一个生成器函数,并使用
contextlib.contextmanager
装饰器对其进行装饰。 然后,我们也可以使用with
语句调用该函数。 对于这种方法,函数必须在try
语句中yield
资源,并且释放资源的__exit__
方法的所有内容现在都在相应的finally
语句内。生成器首先获取资源。 然后,它暂时挂起其自己的执行并 产生 资源,以便调用者可以使用它。 当调用者离开
with
上下文时,生成器继续执行并释放finally
语句中的资源。