目录:
1.上下文管理对象
2.上下文管理的安全性
3.with语句
4.exit方法的参数
1.上下文管理对象
当一个对象同时出现了enter()和exit()方法,它就属于上下文管理的对象
方法 意义
__enter__ 进入与此对象相关的上下文,如果存在该方法,with语法会把该方法的返回值作为绑定到as子句中指定的变量上
__exit__ 退出与对象相关的上下文
import time
class Point:
def __init__(self):
print('init ~~~~~~~~~~~~~~~~~')
time.sleep(1)
print('init over')
def __enter__(self):
print('enter ~~~~~~~~~~~~~~~~~')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit ~~~~~~~~~~~~~~~~~~')
with Point() as p:
print('in with ~~~~~~~~~~~~~~~~~~~')
time.sleep(2)
print('with over')
print('==== end ====')
# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with ~~~~~~~~~~~~~~~~~~~
with over
exit ~~~~~~~~~~~~~~~~~~
==== end ====
实例化对象的时候,并不会调用enter,进入with语句块调用enter方法,然后执行语句体,最后离开with语句块的时候,调用exit方法。
with可以开启一个上下文运行环境,在执行前做一些准备工作,执行后做一些收尾工作。
注意:with并不开启一个新的作用域。
2.上下文管理的安全性
异常对于上下文的影响
import time
class Point:
def __init__(self):
print('init ~~~~~~~~~~~~~~~~~')
time.sleep(1)
print('init over')
def __enter__(self):
print('enter ~~~~~~~~~~~~~~~~~')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit ~~~~~~~~~~~~~~~~~~')
with Point() as p:
print('in with ~~~~~~~~~~~~~~~~~~~')
raise Exception('error')
time.sleep(2)
print('with over')
print('==== end ====')
# 执行结果
init ~~~~~~~~~~~~~~~~~
Traceback (most recent call last):
File "C:/Users/dell/PycharmProjects/pythonProject/test2.py", line 17, in <module>
raise Exception('error')
Exception: error
init over
enter ~~~~~~~~~~~~~~~~~
in with ~~~~~~~~~~~~~~~~~~~
exit ~~~~~~~~~~~~~~~~~~
# 可以看出enter和exit照样执行,上下文管理是安全的
3.with语句
import time
class Point:
def __init__(self):
print('init ~~~~~~~~~~~~~~~~~')
time.sleep(1)
print('init over')
def __enter__(self):
print('enter ~~~~~~~~~~~~~~~~~')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit ~~~~~~~~~~~~~~~~~~')
f = open('animal.py')
with f as p:
print(f)
print(p)
print(f is p)
print(f == p)
# 执行结果
<_io.TextIOWrapper name='animal.py' mode='r' encoding='cp936'>
<_io.TextIOWrapper name='animal.py' mode='r' encoding='cp936'>
True
True
p = Point()
with p as f:
print('in with---------------')
print(p == f)
print('with over')
print('==== end ====')
# 执行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with---------------
True
with over
exit ~~~~~~~~~~~~~~~~~~
==== end ====
with语法,会调用with后的对象的enter方法,如果有as,则将该方法的返回值赋给as子句的变量。
f = p.enter()
4. exit方法的参数
__enter__方法没有参数
__exit__方法有3个参数,__exit__(self,exc_type,exc_value,traceback)
exc_type: 异常类型
exc_value: 异常的值
tracebask: 异常的追踪信息
__exit__方法返回一个等效True的值,则压制异常,否则,继续抛出异常
例1:
存在未捕获异常
import time
class Point:
def __init__(self):
print('init ~~~~~~~~~~~~~~~~~')
time.sleep(1)
print('init over')
def __enter__(self):
print('enter ~~~~~~~~~~~~~~~~~')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(1,exc_type)
print(2,exc_val)
print(3,exc_tb)
print('exit ~~~~~~~~~~~~~~~~~~')
p = Point()
with p as f:
print('in with--------------------')
raise Exception('Error')
print('with over')
print('==== end ====')
# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with--------------------
1 <class 'Exception'>
2 Error
3 <traceback object at 0x0000024E29255408>
exit ~~~~~~~~~~~~~~~~~~
Traceback (most recent call last):
File "C:/Users/dell/PycharmProjects/pythonProject/test2.py", line 22, in <module>
raise Exception('Error')
Exception: Error
例2:
捕获异常
import time
class Point:
def __init__(self):
print('init ~~~~~~~~~~~~~~~~~')
time.sleep(1)
print('init over')
def __enter__(self):
print('enter ~~~~~~~~~~~~~~~~~')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(1,exc_type)
print(2,exc_val)
print(3,exc_tb)
print('exit ~~~~~~~~~~~~~~~~~~')
p = Point()
with p as f:
print('in with--------------------')
try:
raise Exception('Error')
except:
print('catch my exception')
print('with over')
# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with--------------------
catch my exception
with over
1 None
2 None
3 None
exit ~~~~~~~~~~~~~~~~~~
==== end ====
网友评论