Python 上下文管理器
什么是上下文管理器?
- context manager
- 一个上下文管理器是一个对象
- 它定义了运行时的上下文
- 使用 with 语句来执行
with 语句
with context as ctx:# 使用这个上下文对象
# 上下文对象已经被清除
这里我们使用 Python的文件操作 打开一个文件并写入一段话
instance = open('data.txt', 'w') # 打开文件
instance.write('What a wonderful house')
instance.close() # 关闭文件
对于上面的代码,我们可以用 with 语句进行代替,并且只需要两行。
with open('data.txt', 'w') as instance:instance.write('What a wonderful house')
这是因为在 with 语句结束时,会自动调用文件的关闭 close 函数,避免出现异常。
上下文管理器的协议
一个上下文管理器需要实现如下方法:
- __enter__() 安装上下文,可以返回对象
- __exit__() 清楚释放对象
这里我们举个计算一段程序用时时长的例子,time.perf_counter
是用于测量代码执行时间的功能。它返回一个高分辨率的性能计数器,通常用于测量短时间内的代码执行时间。
import timestart = time.perf_counter()
list1 = []
for i in range(1, 10000):list1.append(i ** 2)end = time.perf_counter()
elapsed = end - start
print(elapsed)
为了实现对于任意代码段都可以调用这个计算时长的例子,我们定义 Timer 类来实现整个程序流程,__enter__作为进入方法,__exit()__作为退出方法。
class Timer:def __init__(self):self.elapsed = 0def __enter__(self):self.start = time.perf_counter()return self # 必须实现def __exit__(self, exc_type, exc_val, exc_tb):self.end = time.perf_counter()self.elapsed = self.end - self.startreturn False # 如果在with范围内出现了异常,在exit的时候可以告诉Python是否继续向外抛出,如果return True,那么就表示不抛出了,return False表示继续抛出。当然如果没有异常,这里return什么就无所谓了
主体调用代码部分。
with Timer() as t:list1 = []for i in range(1, 10000):list1.append(i ** 2)end = time.perf_counter()
print(t.elapsed)
下面我们来解释一下代码的执行流程:
- Time()创建对象,调用我们定义的 __init__初始化方法,实现了变量的初始化
- with 语句会调用 __enter__方法,执行 __enter__方法主体内容,并且将返回值传给 as 后面定义的变量,这里是 t。(所以 t 并不是对 Timer()的引用,而是 Timer().__enter__的返回值。
- 当代码段调用结束时,程序会调用 __exit__ 方法进行退出,生成我们需要的整体代码运行时间变量 elapsed。
也就是说,我们之前使用 with 语句打开文件实现文件的退出,本质上是 open 打开的内置的 __exit__ 函数帮我们实现了这样一个功能。
上下文管理的应用
上下文管理器一般的应用场景:
- 开 - 关
- 锁 - 释放
- 启动 - 停止
- 改变 - 重置