With 关键字
With语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后关闭,线程中锁的获取和释放等。
要使用 with 语句,就需要一个上下文管理器。下面是与上下文管理器有关的概念。
- 上下文管理协议:包含方法 __ enter__() 和 __ exit__() ,支持该协议的对象要实现这两个方法。
- 上下文管理器:支持上下文管理协议的对象,定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。 With 使用和原理
# 语法格式
with context_expression [as target(s)]
with body
# 操作文件
with open(filename) as f:
for line in f:
print line
With 语句在执行时,会首先生成上下文管理器,先调用上下文管理器中的 __ enter__() 方法,然后执行 with 中的代码块,最后不管代码块中有没有发生异常,都会调用上下文管理器中的 __ exit__() 方法。类似 try - finally 的处理。
自定义上下文管理器
1、通常做法
自定义一个类,里面实现 enter() 和 exit() 方法(支持上下文管理协议)
class TimeNow:
def __init__(self, lable):
self.lable = lable
def __enter__(self):
self.start = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
end = time.time()
logger.info("label: %s, cost time: %s", self.lable, end - self.start)
2、简单做法
使用 contextlib 中的装饰器 @contextmanager 装饰器,可以实现一个非常简洁的上下文管理器,并且它只需要是个方法就行。
@contextmanager
def time_now(lable):
start = time.time()
try:
yield
finally:
end = time.time()
logger.info("label: %s, cost time: %s", lable, end - start)
yield 之前的代码作为上下文管理器 __ enter__() 执行,可以在这里初始化一些信息,yield 之后的代码都会作为 __ exit__() 执行。