Le comportement n'est pas bien documentée, et est présent dans toutes les versions de Python d'environ 1.5-ish jusqu'à ce que Python 3.4:
Dans le cadre de ce changement, le module globales sont plus de force définie à l' None
pendant interprète d'arrêt dans la plupart des cas, au lieu de compter sur le fonctionnement normal de l'cyclique garbage collector.
La seule documentation pour le comportement, l' moduleobject.c
code source:
/* 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). */
Notez que la définition des valeurs de None
est une optimisation; l'alternative consisterait à supprimer les noms de la cartographie, ce qui conduirait à différentes erreurs (NameError
des exceptions plutôt que AttributeError
s lors de l'utilisation de variables globales à partir d'un __del__
gestionnaire).
Comme vous l'avez découvert sur la liste de diffusion, le comportement est antérieure à l'cyclique garbage collector; il a été ajouté en 1998, tandis que les cycliques garbage collector a été ajoutée en 2000. Puisque la fonction des objets toujours référence au module __dict__
tous les objets de fonction dans un module comportent des références circulaires, c'est pourquoi l' __dict__
besoin de compensation avant de GC est entré en jeu.
Il a été maintenu en place même lorsque cyclique GC a été ajouté, car il peut y avoir des objets avec des __del__
méthodes impliquées dans les cycles. Ces ne sont autrement pas de garbage collector, et le nettoyage du module de dictionnaire serait au moins de supprimer le module __dict__
de ces cycles. Ne pas le faire serait de les garder tous référencés globals de ce module vivant.
Les modifications apportées par PEP 442 , il est maintenant possible pour le garbage collector pour effacer cyclique des références à des objets qui fournissent un __del__
finaliseur, en supprimant la nécessité pour effacer le module __dict__
pour la plupart des cas. Le code est toujours là , mais ce n'est lancée que si l' __dict__
attribut est toujours en vie, même après le déplacement du contenu de sys.modules
de la faiblesse de références et de commencer une collection GC exécuter lorsque l'interprète est en cours de fermeture; le module finaliseur simplement décrémente leur compte de référence.