在this question中,我定义了一个包含上下文管理器的上下文管理器。完成此嵌套的最简单的正确方法是什么?我最终在self.temporary_file.__enter__()
中呼叫了self.__enter__()
。但是,在self.__exit__
中,我很确定我必须在finally块中调用self.temporary_file.__exit__(type_, value, traceback)
,以防引发异常。如果self.__exit__
中出现问题,是否应该设置type_,value和traceback参数?我检查了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)
for l in self.f:
real_f.write(l)
finally:
self.temporary_file.__exit__(type_, value, traceback)
创建上下文管理器的简单方法是使用contextlib.contextmanager
。像这样的东西:
contextlib.contextmanager
然后使用@contextlib.contextmanager
def write_on_change_file(filename):
with tempfile.TemporaryFile('r+') as temporary_file:
yield temporary_file
try:
... some saving logic that you had in __exit__ ...
。with write_on_change_file(...) as f:
语句的主体将“代替” with
执行。如果要捕获主体中发生的任何异常,请将yield
本身包装在yield
块中。
临时文件将始终正确关闭(当其try
块结束时。)>
with
非常适合功能,但是当我需要一个类作为上下文管理器时,我正在使用以下实用程序: