上下文管理器是一个包装任意代码块的对象。
上下文管理器或许被用到最多的就是——作为确保资源被正确清理的一种方式。
常见的上下文管理器的语法
1、with语句
python2.5后引入with语句,使用with语句可以进入上下文管理器。python的内置函数open也能作为上下文管理器使用。
with open('filename','r') as f: content=f.read()
从本质上讲,实际上是with语句对其后代码进行求值(上面就是调用open函数)。该表达式会返回一个对象,该对象包含两个特殊方法:__enter__ 和 __exit__。
__enter__方法返回的结果会被赋予给as之后的变量。
2、enter 和 exit方法
with语句的表达式的作用是返回一个遵循特定协议的对象。具体来说,该对象必须定义一个__enter__方法和一个__exit__方法,且后者接受特定参数。
__enter__方法不接受任何其他参数(除了self),当对象返回时该方法立即执行,然后如果有as 变量(as子句是可选项),返回值将被赋予给as后面的变量。
一般来说,__enter__方法负责执行一些配置.
__exit__方法带有三个位置参数(除了self),一个异常类型,一个异常实例,一个回溯。
如果没有异常,这三个参数全部被设置成None,但如果在代码块内出现异常,则参数被填充。
class ContextManager(): def __init__(self): self.entered = False def __enter__(self): self.entered = True return self def __exit__(self,exc_type,exc_instance,traceback): self.entered = False
该上下文管理器并没有做什么工作,它只是返回自身和设置其entered变量,在进入市设置为True,退出时设置为False。
3、异常处理
上下文管理器必须定义__exit__方法,该方法可以选择性的处理包装代码块中出现的异常,或者处理其他需要关闭上下文管理器状态的事情。
__exit__方法必须定义三个位置参数:
异常类型(本文称exc_type)
异常实例(本文称exc_instance)
回溯选择(本文称traceback)
如果上下文管理器中代码没有发生异常,则所有3个参数的值都为None,如果__exit__方法接收一个异常,就有处理这个异常的义务,方法有三个可选项:
(1)、可以传播异常(因为会在__exit__完成后再次抛出异常)
(2)、可以终止异常
(3)、可以抛出不同的异常
可以通过让一个__exit__方法返回False实现异常的传播,或者通过让__exit__返回True终止异常。另外,如果__exit__抛出一个不同的异常,它将代替异常被发送出去。