上下文管理器__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:UserslwjAppDataLocalProgramsPythonPython37python.exe D:/02Project/pacho/12day/st_上下文管理.py
实例化的时候调用此代码块,若使用as则返回实例对象给as的对象
======
D:2Projectpacho12day
------
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:UserslwjAppDataLocalProgramsPythonPython37python.exe D:/02Project/pacho/12day/st_上下文管理.py
 2 实例化的时候调用此代码块,若使用as则返回实例对象给as的对象
 3 ======
 4 D:2Projectpacho12day
 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
原文地址:https://www.cnblogs.com/wjlv/p/11594092.html