python中的上下文管理器
python中的上下文管理器
python中,我们会经常使用下面的代码:
with open("1.txt", 'r') as f:
f.read()
...
这段代码是用来读某个文件,with在这里可以确保不管使用过程中是否发生异常,都会执行必要的文件关闭操作,释放资源。with语句,简化了代码,有效的避免资源泄漏的发生。
上述代码也可以利用try finally语句完成:
try:
f = open('1.txt', 'r')
finally:
if f:
f.close()
明显看出来这段代码相对更加复杂,python因追求简洁的pythonic编码风格,所以便定义了with写法。
with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放。
上下文管理器
要想理解with,首先要了解 上下文管理器 ,上下文管理器,它是python中的一种协议,实现了这种协议的类的实例,都是上下文管理器对象。
文件的输入输出、数据库的连接断开等,都是很常见的资源管理操作。但资源都是有限的,在写程序时,我们必须保证这些资源在使用过后得到释放,不然就容易造成资源泄露,轻者使得系统处理缓慢,重则会使系统崩溃。上下文管理器,能够帮助你自动分配并且释放资源。
剖析一下上面的with语句:
1. 上下文表达式:with open('test.txt') as f:
2. 上下文管理器:open('test.txt')
3. f是上下文管理器返回的资源对象
4. with关键字表示使用上下文管理器
在python中实现上下文协议并创建上下文管理器对象的方法有两种,一种是基于类的上下文管理器,一种是基于生成器的上下文管理器。
基于类的上下文管理器
用类实现上下文管理器,在类定义的时候,实现两个方法” enter ()”和方法“ exit ()”两个方法即可。其中,方法“ enter ()”返回需要被管理的资源;方法“ exit ()”里通常会存在一些释放、清理资源的操作,比如这个例子中的关闭文件等等。
类实现的上下文管理器的例子:
代码执行的过程:
- 方法__init__()被调用,程序初始化对象FileManager,使得文件名(name)是“test.txt”,文件模式(mode)是‘w’
- 方法enter()被调用,文件test.txt以写入的模式被打开,并且返回资源对象赋给变量f
- 字符串“hello world”被写入文件test.txt
- 方法exit()被调用,负责关闭之前打开的文件流
方法“ exit ()”中的参数“exc_type, exc_val,exc_tb”,分别表示 exception_type、exception_value 和 traceback。当我们执行含有上下文管理器的 with 语句时,如果有异常抛出,异常的信息就会包含在这三个变量中,传入方法“ exit ()”。
基于生成器的上下文管理器
可以使用装饰器 contextlib.contextmanager,来定义自己所需的基于生成器的上下文管理器,用以支持 with 语句。
这段代码中,函数 file_manager() 是一个生成器,当我们执行 with 语句时,便会打开文件,并返回文件对象 f;当 with 语句执行完后,finally中的关闭文件操作便会执行。
两种类型的上下文管理器的比较:
基于类的上下文管理器和基于生成器的上下文管理,这两者在功能上是一致的,但:
- 基于类的上下文管理器更加灵活,适用于大型的系统开发
- 基于生成器的上下文管理器更加方便、简洁,适用于中小型程序
其他讲解python上下文管理器的文章: