python的上下文管理器

发布时间:2022-03-09 09:59:41 人气:240 作者:多测师

  首先,我们来看一下 with 的语法格式:

  with context_expression [as target(s)]: with-body

  with 语法非常简单,我们只需要 with 一个表达式,然后就可以执行自定义的业务逻辑。

  但是,with 后面的表达式是可以任意写的吗?

  答案是否定的。要想使用 with 语法块,with 后面的的对象需要实现「上下文管理器协议」。

  什么是「上下文管理器协议」?

  一个类在 Python 中,只要实现以下方法,就实现了「上下文管理器协议」:

  __enter__:在进入 with 语法块之前调用,返回值会赋值给 with 的 target

  __exit__:在退出 with 语法块时调用,一般用作异常处理

  我们来看实现了这 2 个方法的例子:

  class TestContext: def __enter__(self): print('__enter__') return 1 def __exit__(self, exc_type, exc_value, exc_tb): print('exc_type: %s' % exc_type) print('exc_value: %s' % exc_value) print('exc_tb: %s' % exc_tb)with TestContext() as t: print('t: %s' % t) # Output:# __enter__# t: 1# exc_type: None# exc_value: None# exc_tb: None

  在这个例子中,我们定义了 TestContext 类,它分别实现了 __enter__ 和 exit 方法。

python的上下文管理器

  这样一来,我们就可以把 TestContext 当做一个「上下文管理器」来使用,也就是通过 with TestContext() as t 方式来执行。

  从输出结果我们可以看到,具体的执行流程如下:

  __enter__ 在进入 with 语句块之前被调用,这个方法的返回值赋给了 with 后的 t 变量

  __exit__ 在执行完 with 语句块之后被调用

  如果在 with 语句块内发生了异常,那么 __exit__ 方法可以拿到关于异常的详细信息:

  exc_type:异常类型

  exc_value:异常对象

  exc_tb:异常堆栈信息

  我们来看一个发生异常的例子,观察 __exit__ 方法拿到的异常信息是怎样的:

  with TestContext() as t: # 这里会发生异常 a = 1 / 0 print('t: %s' % t)# Output:# __enter__# exc_type: # exc_value: integer division or modulo by zero# exc_tb: # Traceback (most recent call last):# File "base.py", line 16, in # a = 1 / 0# ZeroDivisionError: integer division or modulo by zero

  从输出结果我们可以看到,当 with 语法块内发生异常后,__exit__ 输出了这个异常的详细信息,其中包括异常类型、异常对象、异常堆栈。

  如果我们需要对异常做特殊处理,就可以在这个方法中实现自定义逻辑。

  回到最开始我们讲的,使用 with 读取文件的例子。之所以 with 能够自动关闭文件资源,就是因为内置的文件对象实现了「上下文管理器协议」,这个文件对象的 __enter__ 方法返回了文件句柄,并且在 __exit__ 中实现了文件资源的关闭,另外,当 with 语法块内有异常发生时,会抛出异常给调用者。

  伪代码可以这么写:

  class File: def __enter__(self): return file_obj def __exit__(self, exc_type, exc_value, exc_tb): # with 退出时释放文件资源 file_obj.close() # 如果 with 内有异常发生 抛出异常 if exc_type is not None: raise exception

  这里我们小结一下,通过对 with 的学习,我们了解到,with 非常适合用需要对于上下文处理的场景,例如操作文件、Socket,这些场景都需要在执行完业务逻辑后,释放资源。

  以上内容为大家介绍了python的上下文管理器,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注多测师。https://www.e70w.com/xwzx/

返回列表
在线客服
联系方式

热线电话

17727591462

上班时间

周一到周五

二维码
线