我们知道在操作文件对象的时候可以这么写
with open(‘a.txt‘,‘‘r) as f: 代码
上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
上下文管理协议.py
class Open: def __init__(self,name): self.name = name def __enter__(self): print(‘执行enter‘) return self def __exit__(self, exc_type, exc_val, exc_tb): print(‘执行exit‘) #with触发的是__enter__ #返回的是self with Open(‘a.txt‘) as f: print(‘===>‘) print(‘===>‘) print(‘===>‘) print(f) print(f.name) #执行完毕with会触发__exit__的运行
正常是在with Open的时候执行__enter__然后执行with下面代码,如果执行代码没有出错exc_type, exc_val, exc_tb的值均为None
假如在with下面执行出现错误则直接跳到__exit__并且不执行往下的代码
上下文管理协议2.py
class Open: def __init__(self,name): self.name = name def __enter__(self): print(‘执行enter‘) return self def __exit__(self, exc_type, exc_val, exc_tb): print(‘执行exit‘) print(‘这是exc_type‘,exc_type) print(‘这是exc_cal‘,exc_val) print(‘这是exc_tb‘,exc_tb) #with触发的是__enter__ #返回的是self with Open(‘a.txt‘) as f: #f是self print(f) print(asdaddgdfg) #打印出对应的属性 print(f.name) #执行完毕with会触发__exit__的运行 print(‘0000000‘)
exc_type, exc_val, exc_tb 三个参数分别对应异常类,异常值,异常追踪信息
如果在__exit__返回一个True则不会报错而把对应的错误输出,不会执行with接着的语句print(f.name),但是会继续执行with下面的语句print(‘0000000‘)
lass Open: def __init__(self,name): self.name = name def __enter__(self): print(‘执行enter‘) return self def __exit__(self, exc_type, exc_val, exc_tb): print(‘执行exit‘) print(‘这是exc_type‘,exc_type) print(‘这是exc_cal‘,exc_val) print(‘这是exc_tb‘,exc_tb) return True #with触发的是__enter__ #返回的是self with Open(‘a.txt‘) as f: #f是self print(f) print(asdaddgdfg) #打印出对应的属性 print(f.name) #执行完毕with会触发__exit__的运行 print(‘0000000‘)
输出如下没有报错(exit把异常吞掉了)
PS:exit运行完毕,with也就结束了
用途或者说好处:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处