一.使用场景
我们经常在进行文件操作时使用with语句来进行操作,这就关系到了上下文管理协议了。
二.使用
在使用with语句时,我们用到了__enter__()和__exit__()方法来进行文件的操作。如下图所示,我们可以自定义一个类似with功能的类来实现该功能。
我们可以发现,with Open() as f,可以看做是,就行了一个实例化的过程,它是先执行,enter()方法,再执行with代码块,最后执行了__exit__()函数,接着才会执行with之后的代码块。
问题1:with代码块中没有异常的情况
没有异常的情况下,直接先Open()进行一个实例化,首先执行__enter()方法,并将返回值赋值给f,再执行with代码块,接着是执行__eixt()方法,最后是执行with之后的代码块。如下图所示:
__exit__()
方法中参数说明:
exc_type:异常类;
exc_val,:异常的值;
exc_tb:异常的追踪信息。
问题2.with代码块中有异常
1.系统内部对异常未做任何处理
如果with中出现了异常,代码会怎样运行呢?见下图:
With语句前面部分执行__enter()方法不变,接着执行with内部的代码块,其中如果有异常,则在发生异常出直接运行__exit()方法,若_exit__()方法返回值不为Ture,则并停止整个程序的运行(因为程序遇到了问题,不再往下运行了)
2.系统内部处理了异常
With语句前面部分执行__enter__()方法不变,接着执行with内部的代码块,其中如果有异常,则在发生异常处直接运行__exit__()方法,若_exit__()方法返回值为Ture,则结束with内部代码,接着执行with之外(之后)的代码块,如下图:
该部分的代码块如下:
class Open():
def __init__(self,name):
self.name = name
def __enter__(self):
print('执行__enter__()方法')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('执行__exit__方法')
print(exc_type)
print(exc_val)
print(exc_tb)
return True
with Open('W.txt') as f:
print("执行with代码块")
print(f.name)
print(f.value) #--->错误在此处
print("执行with最后的代码块") #--->不执行
print("继续with之后的代码块")
三.有何用途? 1.使用with语句的目的是将代码块放入with中执行,with结束后,会自动完成清理工作(内存清理),无需手动干预。 也就是说,在with结束后会自动关闭文件(使用close方法),我们可以想到,不管有没有异常,with代码块最后都会执行__exit__()方法,此时我们可以在__exit__()中完成内存清理工作。 2.在需要管理一些资源如文件、网络连接和锁等编程环境中,我们可以在__exit__方法中自定义释放资源的机制。该功能会有很大的用处。