个人博客
https://blog.csdn.net/cPen_web
#01 上下文管理器的语法
#注:enter方法可以写连接数据库的操作,exit方法写断开连接的操作,用with去管理
#注:with打开的文件对象,就是1个上下文管理器
#注:with语句可以去管理 上下文管理器对象
#注:使用with管理,上下文管理器 不需要自己调用 _enter _、_exit _方法
示例:上下文管理器
#上下文管理器 基本语法
# 1、普通方法打开文件对象
fp = open("test.txt","a+") # a+ 追加写
print(dir(fp))
#结果为 [ …'__enter__', …, '__exit__'…]
#注:有__enter__、__exit__方法,是上下文管理器
fp.write("this is test")
fp.close() #注:处理结束后,把它关掉,不然占资源
# 2、用with语句执行
with open("test.txt","a+") as f: #注:赋给f对象
f.write("write test")
#退出语句执行之后 with自动回收对象
#因为打开的文件对象是上下文管理器
#注:open("test.txt","a+"):上下文表达式
with open("test.txt","a+"):
print("this is test")
#注:不需要上下文管理器对象,可以这样写,没有意义
#迭代器 有 __next__,__iter__方法
#上下文管理器
class ContextManger(): #注:定义1个上下文管理器的对象
def __init__(self):
self.entered = False
def __enter__(self):
print("__enter__ called")
self.entered = True
return self
def __exit__(self, exc_type, exc_val, exc_tb):
#注:exc_type, exc_val, exc_tb 异常类型、异常值、异常嘻嘻
#注:这3个参数不需要自己传,with语句会帮忙管理。这3个参数接收异常信息
print("__exit__ called")
print(exc_type, exc_val, exc_tb)
self.entered = False
cm01 = ContextManger() #注:创建实例对象
print(cm01.entered)
# with ContextManger() as cm02: #注:可以这样管理
with cm01: #注:也可以这么写
print(cm01.entered)
print("this is test")
#结果为
# False
# __enter__ called
# True
# this is test
# __exit__ called
# None None None #注:没有异常就是None,不会报错
#with语句会先执行__enter__方法,退出的时候自动执行__exit__方法
#正常退出的话,__exit__接受的三个参数都是None
#注:不改变代码本身的工作,但又添加额外的功能
#注:上下文管理器 一般来说用作于清理资源、清理连接
# with语句执行的解析
# ·当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法
# ·__exit__()方法有3个参数
# ·如果with语句正常结束,三个参数全部都是 None
#02 上下文管理器异常处理
示例:_exit _
#__exit__ 接受三个参数 异常类,异常值,回溯信息
#上下文管理器 传播异常 终止异常
class MyException():
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val: #注:如果有异常发生
print(f"My exception: {exc_val}")
# return False #注:传播异常,给解释器识别
return True #注:终止异常
with MyException():#使用上下文管理器
print(1+1) #注:没有异常,输出为2
with MyException():
print(1/0) #注:False时 有异常
#False时 结果为 My exception: division by zero
#True时 结果为
# My exception: division by zero #注:True时 不报错,程序不中断
#注:True时 把异常传递出去,给解释器知道
print("end......")
#注:return False 不会执行 end......
#注:return True 执行了 end......
#注:return True时,有点类似于异常捕获机制 try...except...
#注:这个更NB,捕获所有异常
#return True
#try:
# do_sth
#except:
# do_sth
示例:如果是ValueError异常,终止异常;如果不是,传播异常
class MyException():
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if issubclass(exc_type, ValueError): #注:如果是ValueError异常及子类异常
# if exc_type == ValueError: #注:exc_type是类,所以判断条件ValueError类
return True #终止异常
return False #传播异常
with MyException():
print(1+1)
raise ValueError("test value error")
#注:issubclass(exc_type, ValueError) 如果是ValueError异常及子类异常
#03 contextlib模块
示例:contextlib实现上下文管理器
# contextlib实现上下文管理器
#不需要手写class 实现上下文管理器
#使用contextlib模块
import contextlib
@contextlib.contextmanager
def mycontext():
print("enter context")
yield #注:生成器函数
print("exit context")
c1 = mycontext()
print(dir(c1))
#结果为 […'__enter__', '__exit__'…]
#注:使用装饰器后 就是上下文管理器了。不使用装饰器,只是生成器对象
with c1:
print("xxxxxxxxxx")
#结果为
# enter context
# xxxxxxxxxx
# exit context
#注:yield之前是它的__enter__方法,yield之后是它的__exit__方法
#注:这个方法不能终止异常,只能用try...except...进行异常捕获