Call __exit__ on all members of a class
是否有一种Pythonic方法可以自动
1 2 3 4 5 6 7 8 9 10 11 12 | class C: def __init__(self): self.a = open('foo') self.b = open('bar') def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): # Is it correct to just forward the parameters here? self.a.__exit__(self, exc_type, exc_value, traceback) self.b.__exit__(self, exc_type, exc_value, traceback) |
如果不在
假设我拥有的资源不是像示例中那样的
正如我在评论中提到的那样:
I think most helpfull here will be :
contextlib.ExitStack
您可以在
然后使用
1 2 3 4 5 | def __init__(self): self.exit_stack = contextlib.ExitStack() self.exit_stack.__enter__() self.exit_stack.enter_context(open('foo')) .... |
清除所有依赖上下文只需在
或者更好的只是子类
编写自己的
通常,更好的方法是编写基于生成器的上下文管理器。例如。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from contextlib import contextmanager class A: def __init__(self, filename0, filename1, file0, file1): self.filename0 = filename0 self.filename1 = filename1 self.file0 = file0 self.file1 = file1 @classmethod @contextmanager def create(cls, filename0, filename1): with open(filename0) as file0, \ open(filename1) as file1: yield cls(filename0, filename1, file0, file1) with A.create('file0.txt', 'file1.txt') as a: a.do_something() |
这将按定义的顺序打开子上下文管理器,并按照定义的顺序自动关闭它们,传播异常并正确返回值。
要为实例成员提供上下文管理器功能,可以执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class MemberManager: managed_member_names = ('a', 'b', 'c') def __init__(self, a, b, c): self.a, self.b, self.c = a, b, c def __enter__(self): # yield statement means this enter method returns a generator for i in (getattr(self,n) for n self.managed_member_names): with open(i, mode="w") as x: # yield prevents the context manager from exiting yield x def __exit__(self, exc_type, exc_value, traceback): # all items will be closed by __enter__ context manager; nothing needed here pass mm = MemberManager(fname1, fname2, fname3) with mm as open_members: # open_members is a generator/iterator for member in open_members: member.write("foo") |
但请注意,您不能这样做:
1 2 3 | with mm as open_members: open_member_list = list(open_members) open_member_list[0].write("foo") # ValueError: I/O operation on closed file. |
1 2 3 | with C() as c: # stuff # other stuff |
你称这些神奇的功能。在你的情况下,我将调用
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class C: def __enter__(self): self.a = open('foo') self.b = open('bar') return self def __exit__(self, exc_type, exc_value, traceback): self.a.close() self.b.close() def readline_a(self): return self.a.readline() def readline_b(self): return self.b.readline() with C() as c: print(c.readline_a()) print(c.readline_b()) |
打印每个文件