Frage

Ich mache so etwas wie einen Task -Scheduler, der Generatoren als Coroutinen verwendet. Im folgenden Code muss ich das ausführen print cleanup deterministisch.

Aus meiner Interaktion scheint es, dass der Kontextmanager das Objekt an den Müllkollektor beendet. Aber ich weiß es besser, als mich auf das Timing eines GC zu verlassen. Ist es wirklich der GC, der das nennt __exit__ Oder ist es ein anderer Mechanismus?

Wie kann ich strikt erzwingen? print 'cleanup'?

>>> from contextlib import contextmanager
>>> @contextmanager
... def foo():
...     print 'setup'
...     try:
...         yield
...     finally:
...         print 'cleanup'
... 
>>> def bar():
...     with foo():
...         while True:
...             yield 'bar'
... 
>>> b = bar()
>>> b.next()
setup
'bar'
>>> b = None
cleanup
War es hilfreich?

Lösung

Ja, der GC ruft das an __del__ Reinigungshaken des Generators, der wiederum a aufwirft a GeneratorExit in der Generatorfunktion, um den Generator zu beenden (durch Aufrufen generator.close()).

Dies bedeutet der Kontextmanager __exit__ Der Hook wird aufgerufen, wenn eine Generatorfunktion aus dem Speicher gelöscht wird.

Sie können den Generator zuerst manuell selbst schließen, mit generator.close():

b.close()

Andere Tipps

Sie müssen dazu führen, dass der Generator ausgeht. Wenn die Natur des Generators für immer aussah, können Sie Gen.Throw () verwenden, um eine Ausnahme im Generator zu steigern.

Eigentlich habe ich mir nur die Spezifikation für Generatoren angesehen, und sie haben eine Methode Close (), die genau dies macht Alle Kontextmanager werden ihre aufrufen Ausfahrt Methoden. Der Generator frisst die Ausnahme, sodass Sie den Close () -Anruf nicht in einen Try -Block einwickeln müssen:

>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top