上下文管理器的介绍
上下文管理器是装饰器的近亲,与装饰器类似的,它们都是包装其他代码的工具。
装饰器:包装用于定义的代码块。
上下文管理器:可以包装任意格式的代码块。
- 进入上下文管理器时,每次代码执行的一致性
- 当退出上下文管理器时,相关的资源会被正确地回收(即使内部代码出错,退出步骤也会执行)
上下文管理器的应用
上下文管理器被用到最多的就是——作为确保资源正确清理的一种方式。
with语句
python2.5中加入的关键字with,with语句仅仅能对支持上下文管理协议的对象使用。
with语句的表达式的作用是返回一个遵循特定协议的对象,具体来说,该对象必须定义一个__enter__方法和__exit__方法。
with语句解析
语法:
with context_expr as cm:
do_sth()
当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器对象,上下文
管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
- 一旦获得了上下文对象,就会调用它的__enter__()方法
- 将完成with语句块执行前的所有准备工作
- 如果with语句后面跟了as语句,方法返回的结果会被赋值给as关键字后面的变量
- 除了self参数,__enter__方法不接受任何其他参数。
- __enter__方法一般负责执行一些配置
当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法
- __exit__()方法有3个参数
- 如果with语句正常结束,三个参数全部都是 None
- 如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
- 因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法基本是完成的是分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。
支持上下文管理器协议的对象
- file
- decimal.Context
- thread.LockType
- threading.Lock
- threading.RLock
- threading.Condition
- threading.Semaphore
- threading.BoundedSemaphore
上下文管理器异常处理
上下文管理器必须定义__exit__方法,该方法可以选择性地处理包装代码块中出现的异常,或者处理其他需要关闭上下文状态的事情。
__exit__方法接收了异常信息,就有处理这个异常的义务,通常可以做以下几件:
- 传播异常
- 中止异常
- 抛出不同异常
contextlib模块
contextlib模块介绍
contextlib模块实现上下文自动管理,生成器可以用更简单的方法创建上下文管理器。