简介
- 官网
- 他是为with语句提供上下文的工具
- contextlib模块提供了3个对象
- contextmanager:是一个装饰器,用于对生成器函数进行装饰,装饰完成后返回一个上下文管理器对象
- nested :是一个函数,可以将多个上下文管理器组织在一起,避免使用签到的with语句
- closing函数
contextmanager
我们可以下看一下下面的demo
from contextlib import contextmanager
@contextmanager
def test():
print("this is __enter__")
yield "contextmanager demo"
print("this is __exit__")
with test() as t:
print(f"result: {t}")
打印如下
this is __enter__
result: contextmanager demo
this is __exit__
- 我们可以看到
contextmanager
修饰了一个生成器函数 - 被装饰的生成器只能产生一个值,否则会报RuntimeError的错误
- 在yield之前的语句在enter方法中执行,yield之后的语句在exit犯法中执行,而yield产生的值赋值给了as后面的变量
装饰器
contextmanager
只是省略了enter和exit的编写,但是并不负责实现资源的获取与清理工作。所以获取操作需要定义在yield语句之前,清理操作需要定义在yield之后。所以生成器函数需要实现必要的逻辑控制,包括资源访问出现错误是抛出的异常
nested
nest函数相当于一个语法糖,他可以将上下文管理器组织在一起,避免使用嵌套的with语句
with nested(A(),B(),C()) as (X,Y,Z):
pass
等价于
with A() as X:
pass
with B() as Y:
pass
with C() as Z:
pass
closing
closing适用于提供了close实现的对象,比如网络连接、数据库连接等,也可以在自定义类时通过几口close来执行所需要的资源清理工作
原理
class closing(object):
def __init__(self, thing):
self.thing = thing
def __enter__(self):
return self.thing
def __exit__(self, *exc_info):
self.thing.close()
所以,closing上下文管理器包装起来的对象必须提供close方法,不然就会报AttributeError 的错误
例子
from contextlib import closing
class CloseDemo:
def __init__(self) -> None:
self.acquire()
def acquire(self):
print("lock data")
def free(self):
print("unlock data")
def close(self):
self.free()
with closing(CloseDemo()):
print("use data")
打印如下
lock data
use data
unlock data