上下文管理器
一、上下文管理器的定义
上下文管理器是一个包装任意代码块的对象。上下文管理器保证进入上下文管理器时,每次代码执行的一致性;当退出上下文管理器时,相关的资源会被正确的回收。
值得注意的是,上下文管理器一定能够保证退出步骤的执行。如果进入上下文管理器,根据定义,一定会有退出步骤。即使内部代码抛出了异常,这点也成立。事实上,如果退出步骤处理异常合适,那么上下文管理器的退出代码为处理这类异常提供了一个机会。
因此,上下文管理器的功能类似于执行try、except和finally关键字。通常,这也是一种封装需要被重复使用的try-except-finally结构的有效机制。
上下文管理器被用到最多的就是-----作为确保资源被正确清理的一种方式。
二、上下文管理器的语法
例:打开文件
>>> try:
my_file = open('/pyFile/test.txt', 'r')
contents = my_file.read()
finally:
my_file.close()
使用finally子句确保无论发生什么,my_file文件都将被关闭。假如读取文件时发生错误,或者其他地方出现问题,finally子句仍然会执行,而my_file文件会关闭。
(1)with语句
使用with语句可以进入上下文管理器。
例:使用上下文管理器完成同样的功能
>>> with open('/pyFile/test.txt', 'r') as my_file:
contents = my_file.read()
注:Python内置的函数open也能作为上下文管理器使用。
从本质上来讲,实际上是with语句对其后代码进行求值(在本例中,就是调用open函数)。该表达式会返回一个对象,该对象包含两个特殊方法:_enter__和__exit_。__enter__方法返回的结果会被赋给as关键字之后的变量。
值得注意的是,在with后的表达式结果没有被赋给所谓的变量,这很重要。实际上,返回值没有赋给任何对象,只有__enter__方法的返回值会被赋给该变量。
简单性是使用上下文管理器的重要原因。然而更为重要的是,记住用于异常处理和清理的代码有时非常复杂,并且在不同的地方应用也非常麻烦。与装饰器相同的是,使用上下文管理器的关键原因在于避免代码重复。
(2)__enter__和__exit__方法
记住,with语句的表达式的作用是返回一个遵循特定协议的对象。具体来说,该对象必须定义一个__enter__方法和一个__exit__方法,且后者必须接受特定的参数。
__enter__方法只接收一个self参数,不接受任何其他参数。当对象返回时该方法立即执行,然后如果有as变量(as子句是可选项),返回值将被赋给as后面使用的变量。一般来说,__enter__方法负责执行一些配置。
__exit__方法带有3个位置参数(不包括传统的self参数):一个异常类型、一个异常实例和一个回溯。如果没有异常,这3个参数全被设置成None,但如果在代码块内有异常发生,则参数被填充。
例:下面的类的实例被用作上下文管理器
>>> cla