我们经常在使用某个对象的时候,是需要一定的运行环境的。在使用它之前,要提供一些必要条件,使用结束后,要恢复一些必要条件。上下文管理器的目的就是为了帮我们自动来处理这些前提条件和善后工作的。
举个例子,对于file对象,我们在使用之后要关闭这个file对象,可以手动,也可以使用上下文管理器自动关闭。
一、自定义创建上下文管理器
自定义创建上下文管理器示例代码:
path=r'd:/xx.txt'
mode='w'
file=open(path,mode)
class _File(object):
def __init__(self,path,mode):
self.path=path
self.mode=mode
def __enter__(self):
self.file=open(self.path,self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with _File(path,mode) as fp:
fp.write('zheshishenmdongxi')
只要实现了__enter__()方法和__exit__()方法的对象,就是上下文管理器。上下文管理器一般与with...as...共同使用。
具体执行步骤为:
1. 执行 _File(path,mode) 以获取上下文管理器
2. 加载上下文管理器的 __exit__() 方法以备稍后调用
3. 调用上下文管理器的 __enter__() 方法
4. 如果有 as var 从句,则将 __enter__() 方法的返回值赋给 var(这里返回的是self,即_File对象)
5. 执行子代码块 fp.write('zheshishenmdongxi')
6. 调用上下文管理器的 __exit__() 方法,如果 fp.write('zheshishenmdongxi')的退出是由异常引发的,那么该异常的 type、value 和 traceback 会作为参数传给 __exit__(),否则传三个 None。此时可判断这三个参数的值来对异常做出相应反应。
7. 如果fp.write('zheshishenmdongxi') 的退出由异常引发,并且 __exit__() 的返回值等于 False,那么这个异常将被重新引发一次;如果 __exit__() 的返回值等于 True,那么这个异常就被无视掉,继续执行后面的代码。
具体创建步骤参照:
二、Python 标准库 contextlib 构建上下文管理器
自定义上下文管理器还要书写__enter__和__exit__两个函数,还是很麻烦,python标准库内置了contextlib模块,可以更加快速的实现上下文管理器功能。
具体参照廖雪峰教程和上述文章
from contextlib import contextmanager
@contextmanager
def manager():
print('aaa')
yield
print('ccc')
with manager():
print('bbb')
输出:
aaa
bbb
ccc
contextmanager以装饰器的方式构建上下文管理器。
yield语句及之前代码相当于__enter__语句的代码;yield语句之后相当于__exit__语句里的代码,yield返回的值就是with...as var这里的var.