Python with、__enter__()、__exit__()用法
with语法格式:
with EXPR as Variable:
BLOCK
语法解释:
-
EXPR可以是任意表达式;
-
as Variable是可选的
-
as的作用类似于=赋值。
一般的执行过程是这样的:
-
执行EXPR,生成上下文管理器context_manager;
-
获取上下文管理器的__exit()__方法,并保存起来用于之后的调用;
-
调用上下文管理器的__enter__()方法;
-
如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的 Variable;
-
执行 BLOCK 中的代码块;
-
最后调用__exit__退出代码
# with 的工作流程 class Sample: def __enter__(self): print("In __enter__()") return "Foo" def __exit__(self, type, value, trace): print("In __exit__()") def get_sample(): return Sample() with get_sample() as sample: # __enter__() 返回的值赋值给 as 后的变量 sample print("sample:", sample) # 此时sample 为 __enter__()的返回值 """ 输出: In __enter__() sample: Foo In __exit__() """
with真正强大之处是它可以处理异常:
-
__exit__方法有三个参数val,type 和 trace,在with后面的代码块抛出任何异常时,__exit__()方法被执行。
-
异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,可以通过trace打印抛出的异常。
-
开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。
# with真正强大之处是它可以处理异常 class Sample: def __enter__(self): return self def __exit__(self, type, value, trace): print("type:", type) print("value:", value) print("trace:", trace) def do_something(self): bar = 1/0 return bar + 10 with Sample() as sample: sample.do_something() """ 输出: type: <class 'ZeroDivisionError'> value: division by zero trace: <traceback object at 0x7f9f2b33e680> 发生异常: ZeroDivisionError division by zero File "/Users/Shared/script/practice/Untitled-1.py", line 34, in do_something bar = 1/0 File "/Users/Shared/script/practice/Untitled-1.py", line 38, in <module> sample.do_something() """