对于某些任务,通常需要多个具有明确释放资源的对象 - 例如,两个文件; 当任务是使用嵌套with块的函数的本地任务时,这很容易完成,或者 - 甚至更好 - with具有多个with_item子句的单个块:
with open('in.txt', 'r') as i, open('out.txt', 'w') as o:
# do stuff
Run Code Online (Sandbox Code Playgroud)
OTOH,当这些对象不仅仅是函数作用域的本地对象,而是由类实例拥有 - 换句话说,上下文管理器如何构成时,我仍然很难理解它应该如何工作.
理想情况下,我想做的事情如下:
class Foo:
def __init__(self, in_file_name, out_file_name):
self.i = WITH(open(in_file_name, 'r'))
self.o = WITH(open(out_file_name, 'w'))
Run Code Online (Sandbox Code Playgroud)
并有Foo自己变成上下文管理,处理i和o,这样,当我做
with Foo('in.txt', 'out.txt') as f:
# do stuff
Run Code Online (Sandbox Code Playgroud)
self.i并self.o按照您的预期自动处理.
我修改了写东西,比如:
class Foo:
def __init__(self, in_file_name, out_file_name):
self.i = open(in_file_name, 'r').__enter__()
self.o = open(out_file_name, 'w').__enter__()
def __enter__(self):
return …Run Code Online (Sandbox Code Playgroud) 在这个问题中,我定义了一个包含上下文管理器的上下文管理器.完成此嵌套最简单的正确方法是什么?我最后打电话来self.temporary_file.__enter__()了self.__enter__().但是,self.__exit__我很确定我必须调用self.temporary_file.__exit__(type_, value, traceback)finally块,以防引发异常.如果出现问题,我应该设置type_,value和traceback参数self.__exit__吗?我检查过contextlib,但找不到任何实用程序来帮助解决这个问题.
来自问题的原始代码:
import itertools as it
import tempfile
class WriteOnChangeFile:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.temporary_file = tempfile.TemporaryFile('r+')
self.f = self.temporary_file.__enter__()
return self.f
def __exit__(self, type_, value, traceback):
try:
try:
with open(self.filename, 'r') as real_f:
self.f.seek(0)
overwrite = any(
l != real_l
for l, real_l in it.zip_longest(self.f, real_f))
except IOError:
overwrite = True
if overwrite:
with open(self.filename, 'w') as real_f:
self.f.seek(0) …Run Code Online (Sandbox Code Playgroud)