python中的__enter__ __exit__
2018-09-17 22:50
627 查看
我们前面文章介绍了迭代器和可迭代对象,这次介绍python的上下文管理。在python中实现了__enter__和__exit__方法,即支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 __enter__ 方法。with语句运行结束后,会在上下文管理器对象上调用 __exit__ 方法
with的语法:
这是上面语法的伪代码:
1、生成上下文管理器mgr
2、如果没有发现__exit__, __enter__两个方法,解释器会抛出AttributeError异常
3、调用上下文管理器的 __enter__() 方法
4、如果语法里的as VAR没有写,那么 伪代码里的 VAR= 这部分也会同样被忽略
5、如果BLOCK中的代码正常结束,或者是通过break, continue ,return 来结束,__exit__()会使用三个None的参数来返回
6、如果执行过程中出现异常,则使用 sys.exc_info的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)
之前我们对文件的操作是这样的:
现在有了with语句可以使代码更加简洁,减少编码量,下面的语句会在执行完后自动关闭文件(即使出现异常也会)。:
一个例子:
返回:
这个例子里面__enter__没有返回,所以with语句里的"as t"到的是None,修改一下上面的例子:
返回:
如果在__init__或者__enter__中抛出异常,则不会进入到__exit__中:
返回:
如果在__exit__中返回True,则不会产生异常:
返回:
参考: https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p03_make_objects_support_context_management_protocol.html?highlight=with https://docs.python.org/3/library/stdtypes.html#typecontextmanager https://www.python.org/dev/peps/pep-0343/
with的语法:
with EXPR as VAR: BLOCK
这是上面语法的伪代码:
mgr = (EXPR) exit = type(mgr).__exit__ # Not calling it yet value = type(mgr).__enter__(mgr) exc = True try: try: VAR = value # Only if "as VAR" is present BLOCK except: # The exceptional case is handled here exc = False if not exit(mgr, *sys.exc_info()): raise # The exception is swallowed if exit() returns true finally: # The normal and non-local-goto cases are handled here if exc: exit(mgr, None, None, None)
1、生成上下文管理器mgr
2、如果没有发现__exit__, __enter__两个方法,解释器会抛出AttributeError异常
3、调用上下文管理器的 __enter__() 方法
4、如果语法里的as VAR没有写,那么 伪代码里的 VAR= 这部分也会同样被忽略
5、如果BLOCK中的代码正常结束,或者是通过break, continue ,return 来结束,__exit__()会使用三个None的参数来返回
6、如果执行过程中出现异常,则使用 sys.exc_info的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)
之前我们对文件的操作是这样的:
try: f = open('filename') except: print("Unexpected error:", sys.exc_info()[0]) else: print(f.readlines()) f.close()
现在有了with语句可以使代码更加简洁,减少编码量,下面的语句会在执行完后自动关闭文件(即使出现异常也会)。:
with open('example.info', 'r') as f: print(f.readlines())
一个例子:
class TmpTest: def __init__(self,filename): self.filename=filename def __enter__(self): self.f = open(self.filename, 'r') # return self.f def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() test=TmpTest('file') with test as t: print ('test result: {}'.format(t))
返回:
test result: None
这个例子里面__enter__没有返回,所以with语句里的"as t"到的是None,修改一下上面的例子:
class TmpTest: def __init__(self,filename): self.filename=filename def __enter__(self): self.f = open(self.filename, 'r') return self.f def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() test=TmpTest('file') with test as t: print ('test result: {}'.format(t))
返回:
test result: <_io.TextIOWrapper name='file' mode='r' encoding='cp936'>
如果在__init__或者__enter__中抛出异常,则不会进入到__exit__中:
class TmpTest: def __init__(self,filename): self.filename=filename print("__init__") raise ImportError def __enter__(self): self.f = open(self.filename, 'r') print("__enter__") return self.f def __exit__(self, exc_type, exc_val, exc_tb): print("__exit__") self.f.close() test=TmpTest('file') with test as t: print ('test result: {}'.format(t))
返回:
__init__ Traceback (most recent call last): File "D:/pythonScript/leetcode/leetcode.py", line 14, in <module> test=TmpTest('file') File "D:/pythonScript/leetcode/leetcode.py", line 5, in __init__ raise ImportError ImportError
如果在__exit__中返回True,则不会产生异常:
class TmpTest: def __init__(self,filename): self.filename=filename print("__init__") def __enter__(self): self.f = open(self.filename, 'r') print("__enter__") return self.f def __exit__(self, exc_type, exc_val, exc_tb): print("__exit__ {} ".format(exc_type)) self.f.close() return True test=TmpTest('file') with test as t: print ('test result: {}'.format(t)) raise ImportError print("no error")
返回:
__init__ __enter__ test result: <_io.TextIOWrapper name='file' mode='r' encoding='cp936'> __exit__ <class 'ImportError'> no error
参考: https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p03_make_objects_support_context_management_protocol.html?highlight=with https://docs.python.org/3/library/stdtypes.html#typecontextmanager https://www.python.org/dev/peps/pep-0343/
相关文章推荐
- python知识点:上下文管理器[__enter__ 和 __exit__ ]
- python with..as.. __call__ __enter__ __exit__
- Python概念-上下文管理协议中的__enter__和__exit__
- Python with解析 __enter__()、__exit__() (十五)
- python __enter__ 与 __exit__的作用,以及与 with 语句的关系
- python基础----实现上下文管理协议__enter__和__exit__
- python ------------- __enter__(),__exit__(),with
- python __enter__ 与 __exit__的作用,以及与 with 语句的关系
- python安装模块的时候报错error: command 'gcc' failed with exit status 1
- python中sys.exit() os._exit() exit() quit()的简单使用
- Python os._exit() sys.exit() exit()区别
- python | exit
- CentOS7上 pip install MySQL-python 安装失败(error: command 'gcc' failed with exit status 1)的解决办法
- centos7 安装mysql--python模块出现EnvironmentError: mysql_config not found和error: command 'gcc' failed with exit status 1
- Page-Enter、Page-Exit的使用
- python unit test to assert a method calls sys.exit()
- 安装Python的psutil模块时报错:error: command 'gcc' failed with exit status 1
- Error creating Django application: Error on python side. Exit code: 1的解决办法
- 【ZZ】windows+python2.7在IDLE中执行sys.exit()出现的问题及解决方案
- 笨办法学python笔记(习题35)——exit()用法