python的with语句用于创建上下文管理器,它会自动获取和释放资源。
通过as关键字将上下文管理器返回的对象赋值给一个变量。
用法
with exp as var:
#with 语句代码块
描述
exp返回支持管理器协议的对象;
var 变量不是存放exp的返回值,而是存放管理器协议对象的__enter__()方法的返回值;
通过with调用exp获得上下文管理器,将管理器对象的__enter__()方法返回的值赋值给var;
with的用途包括:打开和关闭文件,创建和释放锁,保存和恢复全局状态;
with打开文件执行完后会自动关闭文件;
通过文件对象的closed查看文件是否关闭;
示例-with/as
>>> fpath=r'E:\documents\F盘\ls.txt'
>>> with open(fpath,encoding='utf-8') as f:
for l in f:
print(l)
print(f.closed) # 未关闭f,返回False
梯阅线条
False
# 执行完with,自动关闭f,返回True
>>> f.closed
True
实例-try/finally
>>> fpath=r'E:\documents\F盘\ls.txt'
>>> f=open(fpath,encoding='utf-8')
>>> try:
for l in f:
print(l)
finally:
f.close()# 手动关闭文件
梯阅线条
通过重载__enter__和__exit__方法,实现自定义的环境管理器,然后使用with进行调用。
用法
(1)定义一个类,包括__enter__和__exit__方法;
(2)__enter__方法,返回类实例对象;赋值给as语句的var变量。当然,也可以返回其它值;
(3)__exit__方法,如果入参type为None则对应with代码块没有异常,不用返回任何内容,相当于返回None,效果类似返回False;
如果入参type为非None则对应with代码块触发过异常,需返回False,将异常向with外传递;注,也可不返回False,因为不返回任何内容则默认返回None,效果类似返回False,显式返回False提高代码可读性;
描述
with语句使用环境管理器步骤:
(1) with调用exp获得环境管理器对象,环境管理器对象必须有__enter__和__exit__方法;
(2) 调用环境管理器对象的__enter__方法,并且将__enter__方法返回值赋值给变量var,如果有as var语句的话;
(3) 执行with语句代码块;
(4) 如果with语句代码块触发异常,则调用管理器对象的__exit__(type,value,traceback)方法,并且入参送非None;如果__exit__返回假,则异常被重新触发,否则异常会终止,通常情况要返回假重新触发异常传递到with语句之外;
(5) 如果with语句代码块没有异常,则调用管理器对象的__exit__(type,value,tracebakc)方法,并且入参都为None;
示例-自定义上下文管理器
>>> class WithAsC:
def msg(self,arg):
print('运行',arg)
def __enter__(self):
print('开始执行 with 代码块')
return self
def __exit__(self,exc_type,exc_value,exc_tb):
if exc_type is None:
print('没有异常,正常退出')
else:
print('触发异常,向with传递异常',exc_type)
return False
>>> with WithAsC() as wac:
wac.msg('梯阅线条')
print('正常运行')
开始执行 with 代码块
运行 梯阅线条
正常运行
没有异常,正常退出
>>> with WithAsC() as wac:
wac.msg('梯阅线条')
raise TypeError
print('手动触发异常执行不到此')
开始执行 with 代码块
运行 梯阅线条
触发异常,向with传递异常 <class 'TypeError'>
Traceback (most recent call last):
File "<pyshell#82>", line 3, in <module>
raise TypeError
TypeError
实例-查看文件对象的管理器协议
>>> fpath='E:\documents\F盘\ls.txt'
>>> f=open(fpath,encoding='utf-8')
>>> hasattr(f,'__enter__')
True
>>> hasattr(f,'__exit__')
True
# __enter__返回值 与 f 一致
>>> help(f.__enter__)
Help on built-in function __enter__:
__enter__(...) method of _io.TextIOWrapper instance
>>> type(f)
<class '_io.TextIOWrapper'>