This PEP adds a new statement "with" to the Python language to make it possible to factor out standard uses of try/finally statements.
In this PEP, context managers provide enter() and exit() methods that are invoked on entry to and exit from the body of the with statement.
对于下面的操作:
with EXPR as VAR:
BLOCK
等价于
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
# 将__enter__函数调用的返回值返回给VAR
VAR = value # Only if "as VAR" is present
# 执行BLOCK
BLOCK
except:
# 异常处理,The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# 清理,The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
1. 缘起
Python中,打开文件的操作是非常常见的,也是非常方便的,那么如何优雅的打开一个文件?大部分的同学会这样实现:
大家都知道,这样写可以自动处理资源的释放、处理异常等,化简了我们打开文件的操作,那么,
with
到底做了什么呢?从《Python学习手册》中是这么描述的:
也就是说对于代码:
with语句的实际工作方式:
with/as语句的设计,是为了让必须在程序代码块周围发生的启动和终止活动一定会发生。和try/finally语句(无论异常是否发生其离开动作都会执行)类似,但是with/as有更丰富的对象协议,可以定义进入和离开的动作。
2. 设计的初衷
with/as语句的设计的初衷,在PEP343中是这么描述的:
对于下面的操作:
等价于
我们可以看到上述代码完整的处理了初始化及异常/正常场景的清理操作,这便是
with
的设计思想,化简了冗余的代码,把那些重复的工作以及异常处理操作交给写“EXPR”源码(比如open操作)的同学。3. 更深入的学习
我们继续深入的看下Python3中enter和exit的实现:
和我们预期的一致,在enter中返回了这个IO对象,然后在exit中,进行了清理。
参考资料