什么是Python中Context上下文管理器

上下文管理器是 Python 的一个实用功能。它们之所以如此有用,是因为它们能够正确响应模式。在很多情况下,我们想要运行一些具有前置条件和后置条件的代码,这意味着我们想要分别在主要操作之前和之后运行某些操作。上下文管理器是这些情况下非常有用的工具。

资源处理上下文
大多数情况下,我们看到上下文管理器与资源管理有关。例如,在打开文件的情况下,我们希望确保在处理后关闭它们,或者如果我们打开与服务甚至套接字的连接,我们希望确保相应地关闭它。在所有这些情况下,我们都需要考虑释放已分配的所有资源,而一个干净的方法是使用 finally 块。

让我们看一个例子:

file_data = open(filename)
try:
    process_file(file_data)
finally:
    file_data.close()


如下所示,使用 with 语句是实现上述任务的更好的 pythonic 方法:

with open(filename) as file_data:
    process_file(file_data)

with 语句(PEP-343)进入上下文管理器

在这种情况下,open 函数实现了上下文管理器协议,这意味着当代码块结束时,文件将被自动关闭,即使发生了异常。Python 中的 with 语句是一个强大的工具,旨在简化常见的资源管理模式。

上下文管理器由两个神奇的方法组成:

  • enter 
  • exit
在上下文管理器的第一行,with 语句将调用第一个方法 enter ,这个方法返回的内容将被赋值给 "as "后面的变量。

执行这一行后,代码将进入一个新的上下文,在这个上下文中可以运行任何其他 Python 代码。

在该代码块的最后一条语句之后,上下文将被退出,这意味着 Python 将调用 exit 方法。

如果上下文管理器代码块中出现异常或错误,exit 方法仍会被调用,这有助于安全地管理清理工作。

上下文管理器是一种很好的方法,可以将应该保持独立的代码部分隔离开来。


自定义上下文管理器
除了资源处理上下文管理器,我们还可以创建自定义上下文管理器。让我们来看一个自定义上下文管理器的例子,它可以测量代码块的执行时间:

import time

class Timer:
    def <strong>init</strong>(self):
        self.start = None
        self.end = None
        self.elapsed = None

    def <strong>enter</strong>(self):
        self.start = time.time()  
        return self # This allows you to get data within the with block
    
    def <strong>exit</strong>(self, exc_type, exc_val, exc_tb):
        self.end = time.time()
        self.elapsed = self.end - self.start

with Timer() as timer:
    # Code to be timed goes here
    time.sleep(1)  # Simulate some work

print(f"Elapsed time: {timer.elapsed:.4f} seconds")

如上例所示,with 语句创建了一个 Timer 上下文管理器实例,而要计时的代码就在 with 代码块中。退出代码块后,经过的时间会自动计算出来,并显示在 timer.elapsed 属性中。简而言之,该计时器可用于对代码的各个部分进行剖析。