start - threading python ejemplos
¿Dónde está documentado el procedimiento de apagado de Python? (2)
El comportamiento no está bien documentado, y está presente en todas las versiones de Python desde aproximadamente 1.5-ish hasta Python 3.4 :
Como parte de este cambio, los valores globales de los módulos ya no se configuran forzosamente en
None
durante el cierre del intérprete en la mayoría de los casos, sino que se basan en el funcionamiento normal del recolector de basura cíclico.
La única documentación para el comportamiento es el código fuente moduleobject.c
:
/* To make the execution order of destructors for global
objects a bit more predictable, we first zap all objects
whose name starts with a single underscore, before we clear
the entire dictionary. We zap them by replacing them with
None, rather than deleting them from the dictionary, to
avoid rehashing the dictionary (to some extent). */
Tenga en cuenta que establecer los valores en None
es una optimización; la alternativa sería eliminar nombres de la asignación, lo que daría lugar a diferentes errores (excepciones NameError
lugar de AttributeError
s al tratar de usar globales de un manejador __del__
).
Como descubriste en la lista de correo, el comportamiento es anterior al recolector de basura cíclico; se agregó en 1998 , mientras que el recolector de basura cíclico se agregó en 2000 . Dado que los objetos de función siempre hacen referencia al módulo __dict__
todos los objetos de función en un módulo implican referencias circulares, por lo que el __dict__
necesitaba aclarar antes de que el GC entrara en juego.
Se mantuvo en su lugar incluso cuando se agregó GC cíclico, porque podría haber objetos con métodos __del__
involucrados en ciclos. Por lo demás, estos no son recolectables de basura , y limpiar el diccionario del módulo al menos eliminaría el módulo __dict__
de dichos ciclos. No hacer eso mantendría vivas todas las variables globales referenciadas de ese módulo.
Los cambios realizados para PEP 442 ahora hacen posible que el recolector de basura borre las referencias cíclicas con objetos que proporcionan un finalizador __del__
, eliminando la necesidad de borrar el módulo __dict__
para la mayoría de los casos . El código aún está allí, pero esto solo se activa si el atributo __dict__
todavía está activo incluso después de mover el contenido de sys.modules
a referencias débiles y comenzar una recopilación de GC cuando el intérprete se está cerrando; el finalizador del módulo simplemente disminuye su conteo de referencia.
CPython tiene un comportamiento extraño en el que establece módulos en Ninguno durante el apagado. Esto arruina el registro de errores durante el apagado de algún código de multiproceso que he escrito.
No puedo encontrar ninguna documentación de este comportamiento. Se menciona de pasada en PEP 432 :
[...] reduciendo significativamente la cantidad de módulos que experimentarán el comportamiento "módulo global establecido en Ninguno" que se usa para deliberar ciclos de interrupción e intentar liberar más recursos externos de forma limpia.
Hay preguntas ASÍ sobre este comportamiento y la documentación de C API menciona el comportamiento de cierre para intérpretes integrados .
También encontré un hilo relacionado en python-dev y un error relacionado de CPython :
Este parche no cambia el comportamiento de los objetos del módulo que borran su diccionario global tan pronto como se desasignan.
¿Dónde está documentado este comportamiento? ¿Es específico Python 2?
Hay una pequeña cantidad de documentación relacionada en la parte inferior de los documentos de subprocesos :
En segundo lugar, todos los intentos de importación deben completarse antes de que el intérprete comience a cerrarse. [..] El incumplimiento de esta restricción dará lugar a excepciones y bloqueos intermitentes durante el cierre del intérprete (ya que las últimas importaciones intentan acceder a la maquinaria que ya no está en un estado válido).