使用with
语句实现上下文管理器打开多个资源,例如打开两个文件:
import contextlib
@contextlib.contextmanager
def open_files(file1, file2):
try:
f1 = open(file1, 'r')
f2 = open(file2, 'r')
yield (f1, f2)
finally:
f1.close()
f2.close()
with open_files('file1.txt', 'file2.txt') as (f1, f2):
# 使用f1和f2读取文件内容
pass
在Python3中,上下文管理器是一种对象,类似装饰器,它一个包装任意格式的代码块,定义在进入和退出代码块时要执行的操作。上下文管理器一般用来保证在代码块执行完毕后,资源被正确地释放。即使内部代码出错,退出步骤也会执行。因此,上下文管理器一般用作资源自动释放、正确清理的一种方式。
上下文管理器可以使用with
语句来使用,语法如下:
with expression [as variable]:
with-block
其中,expression
是一个返回上下文管理器对象的表达式,variable
是一个可选的变量名,用于将上下文管理器对象赋值给变量。with-block
是一个代码块,它包含要执行的代码。
当进入with
语句时,上下文管理器的__enter__()
方法被调用,它返回一个对象,该对象可以在代码块中使用。当代码块执行完毕时,上下文管理器的__exit__()
方法被调用,它负责清理资源。
上下文管理器可以使用class
语句或contextlib
模块中的contextmanager
装饰器来定义。例如,下面是一个使用class
语句定义的上下文管理器:
class MyContext:
def __enter__(self):
# 进入代码块时执行的操作
return self
def __exit__(self, exc_type, exc_value, traceback):
# 退出代码块时执行的操作
pass
with MyContext() as obj:
# 使用obj执行代码块中的操作
pass
上面的代码中,MyContext
类定义了__enter__()
和__exit__()
方法,这些方法分别在进入和退出代码块时被调用。在with
语句中,MyContext()
创建了一个上下文管理器对象,并将其赋值给变量obj
。在代码块中,可以使用obj
执行操作。
contextlib
模块中的contextmanager
装饰器可以更方便地定义上下文管理器。例如,下面是一个使用contextmanager
装饰器定义的上下文管理器:
from contextlib import contextmanager
@contextmanager
def my_context():
# 进入代码块时执行的操作
yield obj
# 退出代码块时执行的操作
with my_context() as obj:
# 使用obj执行代码块中的操作
pass
上面的代码中,my_context()
函数使用yield
语句返回一个上下文管理器对象,并在yield
语句前后执行进入和退出代码块时的操作。在with
语句中,my_context()
创建了一个上下文管理器对象,并将其赋值给变量obj
。在代码块中,可以使用obj
执行操作。
使用with
语句和contextlib
模块中的contextmanager
装饰器可以实现上下文管理器打开多个资源。
例如,打开两个文件:
import contextlib
@contextlib.contextmanager
def open_files(file1, file2):
try:
f1 = open(file1, 'r')
f2 = open(file2, 'r')
yield (f1, f2)
finally:
f1.close()
f2.close()
with open_files('file1.txt', 'file2.txt') as (f1, f2):
# 使用f1和f2读取文件内容
pass
在open_files
函数中,使用try
和finally
语句打开两个文件,并使用yield
语句将文件对象作为元组返回。在with
语句中,使用元组解包将文件对象赋值给变量f1
和f2
,然后可以使用它们读取文件内容。最后,在finally
语句中关闭文件。
https://blog.csdn.net/Ernestjackson/article/details/126310354