Domanda

Sto realizzando qualcosa come uno scheduler di attività usando i generatori come coroutine. Nel codice seguente, devo eseguire il print cleanup determinalmente.

Sembra che dalla mia interazione rilasciando l'oggetto al Garbage Collector fa uscire il contesto di contesto. Ma so meglio che fare affidamento sui tempi di un GC. È davvero il GC che chiama il __exit__ O è un altro meccanismo?

Come posso forzare rigorosamente 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
È stato utile?

Soluzione

Sì, il GC sta chiamando il __del__ Hook di pulizia del generatore, che a sua volta solleva a GeneratorExit Nella funzione generatore per uscire dal generatore (chiamando generator.close()).

Questo significa il contesto manager __exit__ Hook verrà chiamato ogni volta che una funzione del generatore viene cancellata dalla memoria.

Puoi prima chiudere manualmente il generatore da solo, con generator.close():

b.close()

Altri suggerimenti

Devi far uscire il generatore. Se la natura del generatore deve guardare per sempre, puoi usare Gen.Throw () per aumentare un'eccezione nel generatore.

In realtà, ho appena esaminato le specifiche per i generatori e hanno un metodo vicino () che fa esattamente questo (solleva un'eccezione generatore () all'interno del generatore. Quindi chiama Gen.Close () quando hai finito Qualsiasi manager di contesto invocherà il loro Uscita metodi. Il generatore mangerà l'eccezione in modo da non aver bisogno di avvolgere la chiamata chiusa () in un blocco di prova:

>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top