Python的with原理探究

Python中with原理探究

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。比如上面的代码,通过使用with语句改造,就变成了下面这个样子:

#!/usr/bin/env python

with open('students.txt', 'r') as fileReader:
    for row in fileReader:
        print(row.strip())

可以看到,通过使用with语句重构,代码立马明朗了不少。这里虽然说了with怎么使用,但是并没有说到点上,没法让人真的明白with的原理。

深挖原理
为了更好的掌握with语句的用法,明白其内在的原理。这里就深挖一下with语句的原理,让大家知其然,更知其所以然。

要搞清楚with语句的原理,先要说一下下面这几个概念:

上下文管理协议(Context Management Protocol):包含方法 enter()和__exit__(),支持该协议的对象要实现这两个方法。
上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__()和__exit__()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。
说完上面两个概念,我们再从with语句的常用表达式入手,一段基本的with表达式,其结构是这样的:

with EXPR as VAR:
    BLOCK

其中EXPR可以是任意表达式;as VAR是可选的。其一般的执行过程是这样的:

执行EXPR,生成上下文管理器context_manager;
获取上下文管理器的__exit()方法,并保存起来用于之后的调用;
调用上下文管理器的__enter
()方法;如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的VAR;
执行BLOCK中的表达式;
不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__()方法,exit()方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句break/continue/return,则以None作为参数调用__exit__(None, None, None);如果执行过程中出现异常,则使用sys.exc_info得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback);
出现异常时,如果__exit__(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用做法;如果返回True,则忽略异常,不再对异常进行处理。

猜你喜欢

转载自blog.csdn.net/XRTONY/article/details/114869302