目录

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 ()”里通常会存在一些释放、清理资源的操作,比如这个例子中的关闭文件等等。

类实现的上下文管理器的例子:

https://i-blog.csdnimg.cn/blog_migrate/3d684977db76b0bd9cc83fd78ece119d.png

代码执行的过程:

  1. 方法__init__()被调用,程序初始化对象FileManager,使得文件名(name)是“test.txt”,文件模式(mode)是‘w’
  2. 方法enter()被调用,文件test.txt以写入的模式被打开,并且返回资源对象赋给变量f
  3. 字符串“hello world”被写入文件test.txt
  4. 方法exit()被调用,负责关闭之前打开的文件流

方法“ exit ()”中的参数“exc_type, exc_val,exc_tb”,分别表示 exception_type、exception_value 和 traceback。当我们执行含有上下文管理器的 with 语句时,如果有异常抛出,异常的信息就会包含在这三个变量中,传入方法“ exit ()”。

基于生成器的上下文管理器

可以使用装饰器 contextlib.contextmanager,来定义自己所需的基于生成器的上下文管理器,用以支持 with 语句。

https://i-blog.csdnimg.cn/blog_migrate/d92e00223ef263c2311bcc20ca0bdbee.png

这段代码中,函数 file_manager() 是一个生成器,当我们执行 with 语句时,便会打开文件,并返回文件对象 f;当 with 语句执行完后,finally中的关闭文件操作便会执行。

两种类型的上下文管理器的比较:

基于类的上下文管理器和基于生成器的上下文管理,这两者在功能上是一致的,但:

  • 基于类的上下文管理器更加灵活,适用于大型的系统开发
  • 基于生成器的上下文管理器更加方便、简洁,适用于中小型程序

其他讲解python上下文管理器的文章: