this questionに、私はコンテキストマネージャを含むコンテキストマネージャを定義しました。この入れ子を達成する最も簡単な正しい方法は何ですか?私はself.__enter__()
にself.temporary_file.__enter__()
を呼んでしまった。しかし、self.__exit__
では、例外が発生した場合にfinallyブロックにself.temporary_file.__exit__(type_, value, traceback)
を呼び出す必要があると私は確信しています。 self.__exit__
で何か問題が生じた場合は、type_、value、およびtracebackパラメータを設定する必要がありますか?私はcontextlib
をチェックしましたが、これを助けるユーティリティは見つかりませんでした。コンテキストマネージャを作成する簡単な方法は、contextlib.contextmanager
であるPythonコンテキストマネージャをネストする
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'の使用は便利ですが、手作業で定義された' __enter__'メソッドと '__exit__'メソッドを持つクラスを使うのが適切な場合があります。あなたはそうすることについてアドバイスをしていますか? – Zearin
これは便利です。たとえば、オブジェクトがコンテキストマネージャー以上のことをする必要がある場合です(この場合、@ contextlib.contextmanagerメソッドの追加も考慮する必要があります)。 –