In this question, ho definito un gestore di contesto che contiene un gestore di contesto. Qual è il modo più semplice per realizzare questo annidamento? Ho finito per chiamare self.temporary_file.__enter__()
in self.__enter__()
. Tuttavia, in self.__exit__
, sono abbastanza sicuro di dover chiamare self.temporary_file.__exit__(type_, value, traceback)
in un blocco finally nel caso in cui venga sollevata un'eccezione. Devo impostare i parametri type_, value e traceback se qualcosa va storto in self.__exit__
? Ho controllato contextlib
, ma non ho trovato alcuna utilità per aiutare con questo.Gestori di contesto di Nesting Python
Codice originale da domanda:
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)
Questo è veramente bello. Ho intenzione di lasciare aperta la domanda per un po 'nel caso in cui questa domanda produca altre buone risposte. –
L'uso di '@ contextlib.contextmanager' è comodo, ma ci sono ancora casi in cui è appropriato usare una classe con i metodi' __enter__' e '__exit__' definiti manualmente. Hai qualche consiglio per farlo? – Zearin
Bene, fallo quando è più conveniente, ad esempio quando l'oggetto deve fare qualcosa di più che essere semplicemente un gestore di contesto (anche se in tal caso dovresti anche considerare di aggiungere un metodo @ contextlib.contextmanager). –