python基础----实现上下文管理协议__enter__和__exit__
我们知道在操作文件对象的时候可以这么写
with open('a.txt') as f: '代码块'
上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 5 def __enter__(self): 6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 7 # return self 8 def __exit__(self, exc_type, exc_val, exc_tb): 9 print('with中代码块执行完毕时执行我啊') 10 11 12 with Open('a.txt') as f: 13 print('=====>执行代码块') 14 # print(f,f.name) 15 16 上下文管理协议
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 5 def __enter__(self): 6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 7 8 def __exit__(self, exc_type, exc_val, exc_tb): 9 print('with中代码块执行完毕时执行我啊') 10 print(exc_type) 11 print(exc_val) 12 print(exc_tb) 13 14 15 16 with Open('a.txt') as f: 17 print('=====>执行代码块') 18 raise AttributeError('***着火啦,救火啊***') 19 print('0'*100) #------------------------------->不会执行
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
1 class Open: 2 def __init__(self,name): 3 self.name=name 4 5 def __enter__(self): 6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') 7 8 def __exit__(self, exc_type, exc_val, exc_tb): 9 print('with中代码块执行完毕时执行我啊') 10 print(exc_type) 11 print(exc_val) 12 print(exc_tb) 13 return True 14 15 16 17 with Open('a.txt') as f: 18 print('=====>执行代码块') 19 raise AttributeError('***着火啦,救火啊***') 20 print('0'*100) #------------------------------->会执行
用途或者说好处:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
-----------------------------------------------------------------------------------------------------------------
笔记:
# with open('a.txt','r') as f: # print('--=---->') # print(f.read()) # with open('a.txt', 'r'): # print('--=---->') # class Foo: def __enter__(self): print('=======================》enter') return 111111111111111 def __exit__(self, exc_type, exc_val, exc_tb): print('exit') print('exc_type',exc_type) print('exc_val',exc_val) print('exc_tb',exc_tb) return True # with Foo(): #res=Foo().__enter__() # pass with Foo() as obj: #res=Foo().__enter__() #obj=res print('with foo的自代码块',obj) raise NameError('名字没有定义') print('************************************') print('1111111111111111111111111111111111111111')
1 import time 2 class Open: 3 def __init__(self,filepath,mode='r',encode='utf-8'): 4 self.f=open(filepath,mode=mode,encoding=encode) 5 6 def write(self,line): 7 self.f.write(line) 8 9 def __getattr__(self, item): 10 return getattr(self.f,item) 11 12 def __del__(self): 13 print('----->del') 14 self.f.close() 15 16 def __enter__(self): 17 return self.f 18 def __exit__(self, exc_type, exc_val, exc_tb): 19 self.f.close() 20 21 22 with Open('egon.txt','w') as f: 23 f.write('egontest\n') 24 f.write('egontest\n') 25 f.write('egontest\n') 26 f.write('egontest\n') 27 f.write('egontest\n') 28 29 30 31 32 33 34 35 class Open: 36 def __init__(self,filepath,mode,encode='utf-8'): 37 self.f=open(filepath,mode=mode,encoding=encode) 38 self.filepath=filepath 39 self.mode=mode 40 self.encoding=encode 41 42 def write(self,line): 43 print('write') 44 self.f.write(line) 45 46 def __getattr__(self, item): 47 return getattr(self.f,item) 48 49 def __enter__(self): 50 return self 51 52 def __exit__(self, exc_type, exc_val, exc_tb): 53 self.f.close() 54 return True 55 56 with Open('aaaaa.txt','w') as write_file: #write_file=Open('aaaaa.txt','w') 57 write_file.write('123123123123123\n') 58 write_file.write('123123123123123\n') 59 print(sssssssssssssss) 60 write_file.write('123123123123123\n')