上下文管理器__enter__和__exit__
直接上代码:
1 import os 2 3 class Open(object): 4 def __init__(self, file): 5 self.file = file 6 7 def __enter__(self): 8 print('实例化的时候调用此代码块,若使用as则返回实例对象给as的对象') 9 self.f = open(self.file) 10 return self # 返回实例是为了调用类方法 11 12 def __exit__(self, exc_type, exc_val, exc_tb): # 三个参数分别代表错误类型,错误值,错误追踪traceback 13 print('Exit...') 14 print(exc_tb) 15 print(exc_type) 16 print(exc_val) 17 self.f.close() 18 19 @property # 装饰器,以属性的方式调用方法 20 def say_name(self): 21 return os.path.dirname(os.path.abspath(__file__)) 22 23 24 if __name__ == '__main__': 25 with Open(r'bin/aa.py') as f: # 通过with的方式实例化类,会触发类的__enter__方法,若__enter__有返回值,则把返回值赋值给as的对象 26 print('======') 27 print(f.say_name) 28 print('------') # 以上代码块执行完毕触发__exit__方法 29 print(abcd) # 此处不存在变量abcd,程序会抛出异常并且终止,但是因为有__exit__方法,错误信息会被吞掉,并直接执行__exit__方法 30 print('.....') # 上一行抛异常,此处不会执行 31 print('lalala') # 上一行抛异常,此处不会执行
运行结果:
C:\Users\lwj\AppData\Local\Programs\Python\Python37\python.exe D:/02Project/pacho/12day/st_上下文管理.py 实例化的时候调用此代码块,若使用as则返回实例对象给as的对象 ====== D:\02Project\pacho\12day ------ Exit... <traceback object at 0x0000000001FFDB48> <class 'NameError'> name 'abcd' is not defined Traceback (most recent call last): File "D:/02Project/pacho/12day/st_上下文管理.py", line 29, in <module> print(abcd) # 此处不存在变量abcd,程序会抛出异常并且终止,但是__exit__方法返回为False(with中的代码块出现了异常),错误信息会被吐出,并直接执行__exit__方法 NameError: name 'abcd' is not defined Process finished with exit code 1
下面说下__exit__的返回值,举例:
1 import os 2 3 class Open(object): 4 def __init__(self, file): 5 self.file = file 6 7 def __enter__(self): 8 print('实例化的时候调用此代码块,若使用as则返回实例对象给as的对象') 9 self.f = open(self.file) # 此处是为了能够调用close() 方法 10 return self # 返回实例是为了调用类方法 11 12 def __exit__(self, exc_type, exc_val, exc_tb): # 三个参数分别代表错误类型,错误值,错误追踪traceback 13 print('Exit...') 14 print(exc_tb) 15 print(exc_type) 16 print(exc_val) 17 self.f.close() 18 return True # 如果exit返回True则吞掉所有异常并结束with语句;如果exit返回False,则吐出异常 19 20 @property # 装饰器,以属性的方式调用方法 21 def say_name(self): 22 return os.path.dirname(os.path.abspath(__file__)) 23 24 25 if __name__ == '__main__': 26 with Open(r'bin/aa.py') as f: # 通过with的方式实例化类,会触发类的__enter__方法,若__enter__有返回值,则把返回值赋值给as的对象,即 f = 实例.__enter__() 27 print('======') 28 print(f.say_name) 29 print('------') # 以上代码块执行完毕触发__exit__方法 30 print(abcd) # 此处不存在变量abcd,程序会抛出异常并且终止,但是因为有__exit__方法,错误信息会被吞掉,并直接执行__exit__方法 31 print('.....') # 上一行抛异常,则直接执行exit方法,此行不会被执行,with语句结束 32 print('lalala') # 上一行抛异常,因为exit返回为True,此行会被执行
执行的结果:
1 C:\Users\lwj\AppData\Local\Programs\Python\Python37\python.exe D:/02Project/pacho/12day/st_上下文管理.py 2 实例化的时候调用此代码块,若使用as则返回实例对象给as的对象 3 ====== 4 D:\02Project\pacho\12day 5 ------ 6 Exit... 7 <traceback object at 0x000000000200DB08> 8 <class 'NameError'> 9 name 'abcd' is not defined 10 lalala 11 12 Process finished with exit code 0