原文地址:Python中的With…as语句(简书-惑也)
一、语法
with context as var:
with_suite
with语句
:可以代替try…except…finally语句,使代码更加简洁;context
:通常是表达式,返回一个对象;var变量
:用来保存context返回的对象,可以是单个值或元组;with_suite
:使用变量var对context返回对象进行各种操作的代码段
二、示例
# 查看文件内容
XZ:learn xz$ cat with.txt
with...as...
12345
abcde
In [2]: with open('with.txt','r+') as f:
...: for line in f.readlines():
...: print(line)
...: print('with is closed : ', f.closed)
...:
...:
with...as...
12345
abcde
with is closed : True
- 打开文本
with.txt
,f
变量接收文件对象返回的对象; - 读取文本中的内容,逐行打印;
with
中的代码执行完成后,会自动关闭文件;- 如果
with
语句中没有做try...except
异常处理,出现错误时会直接将异常交给Python解释器抛出,不会自动关闭文件,如果做了try...except
异常处理,出现异常时,会自动关闭文件,再抛出异常。
三、原理
- with语句实质上是上下文管理
- 上下文管理协议:包含2个方法:
__enter__
和__exit__
; - 支持该协议的对象,要实现这2个方法,才能被with语句进行操作。
- 上下文管理器
- 定义执行with语句时建立的运行时上下文,负责执行with语句上下文的进入和退出操作;
- 进入上下文管理器:调用管理器
__enter__
方法,如果设置了as var
语句,变量var接受__enter__
方法的返回值; - 退出上下文管理器:调用管理器的
__exit__
方法。
四、应用场景
- 文件操作
- 进程线程之间互斥对象,如互斥锁
- 自定义的支持上下文的其它操作
五、我的实践
"""
with语句处理异常
我们知道使用try-except-finally语句可以处理异常,接下来我们介绍使用with语句处理与异常相关的工作
with语句支持创建资源,抛出异常,释放资源等操作,并且代码简洁。
with语句格式
with 上下文表达式 [as 资源对象]: 对象操作 说明:
上下文表达式,返回一个上下文管理对象
如果指定了as语句,该对象并不赋值给as子句中的资源对象,而是将上下文管理器的__enter__()方法的返回值赋值给了资源对象。
资源对象可以是单变量,也可以是元组。
使用with语句操作文件对象
"""
with open("test.txt") as file:
for aline in file:
print(aline)
"""
解释说明: 这段代码使用with语句打开文件,如果顺利打开,则将文件对象赋值给file,然后用for语句遍历打印文件的每一行。
当文件操作结束后,with语句关闭文件。如果这段代码运行过程中发生异常,with也会将文件关闭。
这段代码使用finally语句实现如下:
"""
try:
file = open("test.txt")
try:
for aline in file:
print(aline)
except Exception as error:
print(error)
finally:
file.close()
except FileNotFoundError as err:
print(err)
"""
我们也可以给with语句加上异常处理:
"""
try:
with open("test.txt") as file:
for aline in file:
print(aline)
except Exception as error:
print(error)
"""
通过对比可以发现:with语句在进行异常处理时代码简洁很多
特别说明:
不是所有的对象都可以使用with语句,只有支持上下文管理协议的对象才可以。目前支持上下文管理协议的对象如下:
"""
# file
# decimal.Context
# thread.LockType
# threading.BoundedSemaphore
# threading.Condition
# threading.Lock
# threading.RLock
# threading.Semaphore