说起上下文管理器,也许会比较陌生,要是说起下面这个例子,相信大家都非常熟悉,这种打开文件的方式就是使用了上下文管理器。
什么是上下文管理器
语法
说明
为什么要用上下文管理器?
使代码更加优雅,避免了琐碎操作及必要操作步骤的遗忘,一般应用在如下两种场景中:
下文中也会就这两种场景一一举例说明。
自定义上下文管理器
想实现一个上下文管理,首先需要了解什么是上下文管理协议(Context Manager Protocol,上下文管理协议包括两个方法:
也就是说,当我们需要创建一个上下文管理器类型的时候,就需要实现__enter__和__exit__方法,这对方法就称为上下文管理协议,定义了一种运行时上下文环境。
接下来,动手写一个自定义的上下文管理器,示例如下:
上述代码执行结果如下:
通过日志的打印顺序,不难其执行过程,在实际应用中,可以将资源的连接操作放到__enter__中,将资源的关闭操作写在__exit__ 中。
更加优雅的操作资源
在上文中,提到上下文管理器常应用的两个场景,接下来我们看一下第一个场景,更加优雅的操作资源,我们在mysql、sqlite等数据库操作时,经常涉及链接数据库、执行相关操作、关闭链接等操作,让我们上下文管理器是如何优雅的实现数据库链接、执行、关闭操作的,如下:
如上,我们使用上下文管理器优雅的实现数据库的查询,执行上述代码,输出结果如下:
更加优雅的处理异常
介绍完了如何更优雅的操作文件/数据库资源,接下来,看一下上下文管理器常应用到的第二个场景,如何更优雅的处理异常,如下:
以上面的代码为例,“run parse {1}’.format(self.flag)” 将抛出IndexError 异常,接下来我们执行如下代码:
执行上述代码,输出结果如下:
居然没有抛出异常信息,程序运行完成,使用 with 将异常的处理隐藏起来,简化 try/finally 模式,使得代码的可读性更高。这就是上下文管理协议的一个强大之处,异常在__exit__ 中捕获并由我们决定是抛出还是在这__exit__ 中解决。
在__exit__ 里返回 True(默认为返回False,即使代码中没有return),相当于告诉Python解释器,这个异常已经捕获了,不需要往外抛了。若__exit__ 里返回 False,则抛出所触发的异常。如下
执行上述代码,输出结果如下:
我们发现当__exit__ 里返回 False,同时仍然执行了“run close connection ”操作,然后程序抛出所触发的异常,完美。
通过上面几个例子,可以大致总结出with 语句的执行流程:
contextlib 模块
上面自定义上下文管理器,如果应用与一些简单的功能,难免有些繁琐,对于上下文的管理,Python也提供了内建的模块contextlib来实现相同的机制,这种通过生成器和装饰器实现的上下文管理器,看起来比with语句和手动实现上下文管理协议更优雅。
在被装饰的open_file函数里,必须是一个带有yield的生成器,在yield之前的代码,就相当于__enter__方法中的内容,在yield 之后的代码,就相当于__exit__ 方法中的内容。
执行上述代码,运行结果如下:
如果要处理异常,可以改成下面这个样子。
执行上述代码,运行结果如下:
千里之行始于足下,若感兴趣就动手操作一下吧,感谢您的转发、关注支持。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!