Python3基础-上下文管理协议
一.上下文管理协议
操作文件对象的时候可以这样写
with open('a.txt','r+') as f: '代码块'
上述叫做上下文管理协议,即with语句,为了让对象兼容with语句,必须在这个对象的类中声明__enter__ 和__exit__方法
1、__enter__()会在with语句出现(实例化对象)时执行
2、__exit__()会在with语句的代码块执行完毕之后才会执行
class Open: def __init__(self,name,mode): self.name = name self.mode = mode def __enter__(self): #在实例化打开文件即触发,在with时触发 print('执行enter') return self #return 的self 会复制给f,相当于通过Open类实例化对象f def __exit__(self, exc_type, exc_val, exc_tb): ##在with中的代码块执行完毕才会触发 print('执行exit') with Open('a.txt','r+')as f: #会触发enter '执行__enter__',相当于--》f=Open('a.txt').__enter__() print(f) print(f.name) print(f.mode) print('='*10) """ 执行结果 执行enter <__main__.Open object at 0x00FE0BD0> a.txt r+ 执行exit
========== """
二.__exit__
__exit__()中有三个参数分别代表异常类型,异常值和追溯信息,执行了__exit__则表示with语句执行完毕
1、若 __exit__返回值return 不为True,则
1.1 若 with 语句中没有异常,则程序正常执行
1.2 若 with 语句中出现异常,则程序会执行到with中出错的语句并执行__exit__,然后程序终止,‘吐出’异常
class Open: def __init__(self,name,mode): self.name = name self.mode = mode def __enter__(self): #在实例化打开文件即触发,在with时触发 print('执行enter') return self #return 的self 会复制给f,相当于通过Open类实例化对象f def __exit__(self, exc_type, exc_val, exc_tb): ##在with中的代码块执行完毕才会触发 print('执行exit') print(exc_type) print(exc_val) print(exc_tb) with Open('a.txt','r+')as f: #会触发enter '执行__enter__',相当于--》f=Open('a.txt').__enter__() print(f) print(f.age) ##因为f对象没有age属性,则出现异常,程序执行到该句时将异常传递给__exit__的三个参数,并结束程序执行,报错 print(f.name) #该行语句后面的语句都不会执行,包括with语句的以外的语句也不会执行 print(f.mode) #该行语句后面的语句都不会执行,包括with语句的以外的语句也不会执行 print('='*10)
""" Traceback (most recent call last): 执行enter File "D:/pyAuto/pythonDay/pythonbase/类/上下文管理协议.py", line 25, in <module> <__main__.Open object at 0x00A50070> print(f.age) 执行exit AttributeError: 'Open' object has no attribute 'age' <class 'AttributeError'> 'Open' object has no attribute 'age' <traceba
2、若 __exit__返回值return 为True,则
2.1 若 with 语句中没有异常,则程序正常执行
2.2 若 with 语句中出现异常,则程序会执行到with中出错的语句并执行__exit__,'吞掉'异常;然后with语句中剩下的语句不会执行,但是会继续执行with语句以外的语句
class Open: def __init__(self,name,mode): self.name = name self.mode = mode def __enter__(self): #在实例化打开文件即触发,在with时触发 print('执行enter') return self #return 的self 会复制给f,相当于通过Open类实例化对象f def __exit__(self, exc_type, exc_val, exc_tb): ##在with中的代码块执行完毕才会触发 print('执行exit') print(exc_type) print(exc_val) print(exc_tb) return True #或者返回 return 1 with Open('a.txt','r+')as f: #会触发enter '执行__enter__',相当于--》f=Open('a.txt').__enter__() print(f) print(f.age) ##因为f对象没有age属性,则出现异常,程序执行到该句时将异常传递给__exit__的三个参数,并结束程序执行,报错 print(f.name) #该行语句后面的语句不会执行,但是with语句的以外的语句会执行 print(f.mode) #该行语句后面的语句不会执行,但是with语句的以外的语句会执行 print('='*10) """ 执行enter <__main__.Open object at 0x03080070> 执行exit <class 'AttributeError'> 'Open' object has no attribute 'age' <traceback object at 0x030AEC60> ========== """