上下文管理器__enter__和__exit__

Posted wjlv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了上下文管理器__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(rbin/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(rbin/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

 

以上是关于上下文管理器__enter__和__exit__的主要内容,如果未能解决你的问题,请参考以下文章

上下文管理器

自定义上下文管理器

实现文件上下文管理(\_\_enter\_\_和\_\_exit\_\_)

Python进阶-----上下文管理协议(__enter__,__exit)

上下文管理协议with_open,__enter__和__exit__(三十八)

Python中with用法详解