python的上下文管理器,是为了节省是打开某资源后,不管出现什么异常都要关闭的代码try ... finally ...
, 能够简写为with .. as ..
python
上下文管理器的协议包含__enter__
和__exit__
两个方法,在with语句开始运行时,会调用__enter__
方法。with语句结束后,会调用__exit__
方法。测试
建立类,实现__enter__
和__exit__
方法。若是with代码块中抛出异常,exc_type
是异常类型类, exc_val
是异常值,exc_tb
是错误栈对象code
class LookingGlass: def __enter__(self): print('start') return 'running' def __exit__(self, exc_type, exc_val, exc_tb): print('end') def test_1(): with LookingGlass() as what: print(what) Output: start running end
实现一个类感受挺麻烦。利用contextlib.contextmanager装饰方法,咱们能够没必要显式实现协议,利用yield,来分割。yield以前能够看做是__enter__
方法的内容,yield以后能够当作是__exit__
方法的内容。yield生成的就是给as后的变量赋值。对象
from contextlib import contextmanager @contextmanager def context(): print('start') # __enter__ try: yield 'running' # as ... except Exception as e: raise e # 再次抛出异常 finally: print('end') # __exit__ def test_2(): with context() as what: print(what) # raise 测试 Output: start running end
注意: yield语句必定要写在try/except/finally中,由于@contextmanager不会处理with代码块中出现的异常,会在yield中抛出,若是不try/except,程序会停止,__exit__方法都不会执行(即看不到end输出)!资源