Ich habe einen lang laufenden Prozess namens Updater, der über Updates (an ein ETL-System) verfügt. Die Aktualisierungen verfügen über Ressourcenanforderungen, die durch Hinzufügen eines Kontextmanagers zum ExitStack des Updaters verwaltet werden. Einige Updates beinhalten eine neue Konfiguration, was bedeutet, dass betroffene Ressourcen vom Stack freigegeben werden müssen und eine neu konfigurierte Version der Ressource hinzugefügt wird. Ich brauche so etwas wie:So entfernen Sie einen Kontextmanager aus einem ExitStack
with ExitStack() as stack:
ctx_manager = open("file.txt")
f = stack.enter_context(ctx_manager)
...
ctx_pop(ctx_manager, stack) # remove the given context manager from the stack
Im Folgenden ist ein Beispiel für etwas, das ich zu arbeiten bekommen haben, aber es stützt sich auf geschützte Mitglieder zugreifen. Ich hatte gehofft, es könnte eine weniger ‚schmutzige‘ Lösung als diese:
def ctx_pop(cm, stack):
for item in stack._exit_callbacks:
if item.__self__ is cm:
break
else:
raise KeyError(repr(cm))
stack._exit_callbacks.remove(item)
item(None, None, None)
Edit: Hinzugefügt bekannte Lösung
auf den Quellcode der Suche 'ExitStack' verwendet eine' deque' Wrapper speichern für die Kontexte '.__ exit__' Methode, so dass Sie benötigen würde den Wrapper durch den ursprünglichen Kontextmanager identifizieren zu können, was meines Wissens nicht möglich ist. Möglicherweise müssen Sie die Funktionalität von 'ExitStack' neu erfinden (zumindest teilweise), um Kontexte vorzeitig entfernen zu können. –
@ TadhgMcDonald-Jensen danke. Ich habe das gleiche entdeckt, als ich 'ExitStack'-Objekte in einem Jupyter-Notebook untersuchte. Sie haben eine Deque von Schließungen, deren Attribut "__self__" ein Kontextmanager ist. Ich werde Code als bekannte Lösung verwenden, aber ich habe auf eine weniger "Hack" -Lösung gehofft. Ich wollte sehen, ob es eine sauberere Lösung gab, bevor ich Python Ideas einreiche oder sie selbst hinzufüge (was ich vorher noch nie getan habe). – arachnivore