python中的__enter__ __exit__
我们前面文章介绍了迭代器和可迭代对象,这次介绍python的上下文管理。在python中实现了__enter__和__exit__方法,即支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 __enter__ 方法。with语句运行结束后,会在上下文管理器对象上调用 __exit__ 方法
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 + __enter__ + __exit__)
上下文管理协议: with + __enter__ + __exit__ #上下问管理协议: #with + __enter__ + __exit__ class Test(): def __init ...
- python中那些双下划线开头得函数和变量--转载
Python中下划线---完全解读 Python 用下划线作为变量前缀和后缀指定特殊变量 _xxx 不能用'from module import *'导入 __xxx__ 系统定义名字 __x ...
- Python中异常(Exception)的总结
Python中的异常处理 异常处理的语句结构 try: <statements> #运行try语句块,并试图捕获异常 except <name1>: <statement ...
- Python中With的用法
在看Dive Into Python中有关描述文件读写那章节的时候,看到了有关with的用法,查阅下相关资料,记录下来,以备后用. 官方的reference上有关with statement是这样说的 ...
- python中with学习
python中with是非常强大的一个管理器,我个人的理解就是,我们可以通过在我们的类里面自定义enter(self)和exit(self,err_type,err_value,err_tb)这两个内 ...
- Python中的上下文管理器和with语句
Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...
- 整理一下python中with的用法
ith替代了之前在python里使用try...finally来做清理工作的方法.基本形式如下: with expression [as variable]: with-block 当expressi ...
- python python中那些双下划线开头的那些函数都是干啥用用的
1.写在前面 今天遇到了__slots__,,所以我就想了解下python中那些双下划线开头的那些函数都是干啥用用的,翻到了下面这篇博客,看着很全面,我只了解其中的一部分,还不敢乱下定义. 其实如果足 ...
- python中那些双下划线开头得函数和变量
Python中下划线---完全解读 Python 用下划线作为变量前缀和后缀指定特殊变量 _xxx 不能用’from module import *’导入 __xxx__ 系统定义名字 __x ...
随机推荐
- K8s爆严重安全漏洞?有何应对措施与建议
Kubernetes最近爆出严重安全漏洞,影响几乎目前所有的版本.实际影响究竟多大?老版本用户是否必须升级?以下是华为云容器服务团队对该漏洞的分析解读. Kubernetes爆出的严重安全漏洞: 攻击 ...
- Leetcode(力扣) 整数反转
Leetcode 7.整数反转 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例: 输入: -123 输出: -321 注意: 假设我们的环境只能存储得下 32 位的有符 ...
- 作业6--四则运算APP之Sprint计划
1.现状 小组成员各就各位,理顺计划思路,制定工作计划. 2.部分需求索引卡 第一个阶段没有具体功能的实现. 3.任务认领 产品负责人:王宏财 Master:陈思明 项目开发成员:许佳豪.吴旭涛 4. ...
- Beta 冲刺 七
团队成员 051601135 岳冠宇 031602629 刘意晗 031602248 郑智文 031602330 苏芳锃 031602234 王淇 项目进展 岳冠宇 昨天的困难 换了种方法写了搜索栏, ...
- 善用Eclipse的代码模板功能
转载自: 善用Eclipse的代码模板功能 Eclipse是个非常强大的IDE,作为一个JAVA程序员,几乎每天都与它打交道,但是它强大的功能都用到了吗? 今天让我们来看一下Eclipse中的“代码模 ...
- Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
1. 理解 kivy 坐标系统 上一节中,咪博士带大家实现了画板程序的基础框架,以及一个基本的自定义窗口部件(widget).在上一节的末尾,咪博士留了一道关于 kivy 坐标系统的思考题给大家.通过 ...
- python的logging日志模块
1. 简单的将日志打印到屏幕 import logging logging.debug('This is debug message') logging.info('This is info mess ...
- 拿到一个崭新的Linux!
买了服务器,这次买了半年,不能浪费了! 0.准备工作: l查看Ip:ifconfig ip addr 不能上网? 执行以下: vi /etc/sysconfig/network-scripts/if ...
- 【题解】 bzoj1191: [HNOI2006]超级英雄Hero (二分图)
bzoj1191,懒得复制,戳我戳我 Solution: 二分图最大匹配板子题 Attention: 注意题干中的一句话 只有当选手正确回答一道题后,才能进入下一题,否则就被淘汰. Code: //I ...
- 【BZOJ1056】[HAOI2008]排名系统(Splay)
[BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...