Pregunta

Estoy haciendo algo como un programador de tareas que usa generadores como coroutinas. En el siguiente código, necesito ejecutar el print cleanup determinista.

Parece de mi interacción que liberar el objeto al recolector de basura hace que el gerente de contexto salga. Pero, sé mejor que confiar en el momento de un GC. ¿Es realmente el GC que llama al __exit__ ¿O es otro mecanismo?

¿Cómo puedo forzar estrictamente 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
¿Fue útil?

Solución

Sí, el GC está llamando al __del__ CONSTRUICIÓN DE LIMPIEDAD DEL GENERADOR, que a su vez eleva un GeneratorExit en la función del generador para salir del generador (llamando generator.close()).

Esto significa el gerente de contexto __exit__ El gancho se llamará cada vez que se borre una función del generador de la memoria.

Puedes cerrar manualmente el generador tú mismo primero, con generator.close():

b.close()

Otros consejos

Tienes que hacer que el generador salga. Si la naturaleza del generador debe mirar para siempre, puede usar gen.throw () para aumentar una excepción en el generador.

En realidad, solo miré la especificación de generadores, y tienen un método cerrado () que hace exactamente esto (plantea una excepción de generatorexit () dentro del generador. Así que solo llame a gen.close () cuando haya terminado con él Cualquier gerente de contexto invocará su salida métodos. El generador comerá la excepción para que no necesite envolver la llamada Cerrar () en un bloque de prueba:

>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top