!! Python中的with语句通常用于对资源进行访问的场景,比如,文件使用后自动关闭、线程中锁的自动获取和释放等。保证访问过程中无论发生异常都会执行必要的清理操作,以达到释放资源的目的。
本文主要介绍with语句常用的两个应用示例:
1. 使用with语句打开文件
首先在编程目录下创建一个文本文件text
,其中的内容如下图所示:
使用with语句打开文件的语句如下所示:
with open('text', 'r') as f:
text = f.readlines()
读取的text
内容如下图所示:
由此,可以看出with语句只需要两行代码就能实现文件的读取,而且with语句会自动的完成异常处理与文件自动释放。
另外,with语句还可以同时打开多个文件,以达到减少代码量,下面代码实现同时打开两个文件,并分别在两个文件写入相应的内容:
with open('text_1', 'w') as f1, open("text_2", 'w') as f2:
f1.write('这是写入第一个文件的内容')
f2.write('这是写入第二个文件的内容')
执行上面代码后,如果当前目录下有text_1
与text_2
文件则分别写入相应的内容;如果没有则创建这两个文件,并写入相应内容。
2. 自定义上下文管理器
🤔 场景问题分析:在Python编程时通常回到如何正确管理外部资源的问题,比如文件、锁和网络链接等。如果创建与打开资源后,不实现关闭则会出现内存泄漏的问题。
对于上面的问题,我们可以通过基于with语句自定义上下文管理器的调用来解决。通过创建一个实现了__enter__()
与__exit__()
的特殊类方法来创建基于类的上下文管理器。
__enter__(self)
:在进入with
上下文时调用,其返回值绑定到as
后的目标变量;__exit__(self, exc_type, exc_value, exc_tb)
:此方法在执行流离开with上下文时调用。如果发生异常,则exc_type
、exc_value
和exc_tb分别保存异常类型、值和回溯信息。下面代码实现了一个基于with语句的上下文管理器:
# 创建一个基于__enter__()与__exit__()的上下文管理器
class MyContext:
def __enter__(self):
print("进入我的上下文")
return [1, 2, 3]
def __exit__(self, exc_type, exc_value, exc_tb):
print("离开我的上下文")
print(exc_type, exc_value, exc_tb, sep='=====')
# 使用with语句调用上下文管理器
with MyContext() as data:
print(data[0])
代码执行结果如下图所示:
由上图可以看出,使用with语句的上下文管理器的代码执行顺序为:
data = MyContext().__enter__()
,此时输出“进入我的上下文”;print(data[0])
,输出1
;上下文管理器的重要概念如下表所示:
名称 | 内容 |
---|---|
上下文管理协议 | 在Python中主要通过__enter__()方法与__exit__()方法实现 |
上下文管理器 | 实现了__enter__()方法与__exit__()方法就是上下文管理器 |
运行时上下文 | 由上下文管理器创建,在with语句体代码执行之前,通过__enter__()进入,语句体执行结束后,通过__exit__()退出 |
上下文表达式 | 在with关键字后面的表达式,表达式返回上下文管理器对象 |
语句体 | with语句包裹起来的代码 |