Python的关机程序在哪里被logging?

CPython有一个奇怪的行为,在关机期间将模块设置为None。 这closures了我写的一些multithreading代码closures时的错误日志logging。

我无法find这种行为的任何文件。 在PEP 432中提到:

[…]显着减less将经历“模块全局设置为无”行为的模块的数量,该行为被用于审议中断周期并试图干净地释放更多的外部资源。

有关于此行为的SO问题 , C API文档提到了embedded式解释器的closures行为 。

我还在python-dev和相关的CPython bug中find了相关的线程 :

这个补丁不会改变模块对象在解除分配后立即清除其全局variables字典的行为。

这种行为在哪里logging? 是Python 2具体吗?

这种行为没有很好的文档记载,并且在所有版本的Python中都存在,从Python 1.5 1.5:

作为这种改变的一部分,在大多数情况下,在解释器closures期间,模块全局variables不再被强制设置为None ,而是依赖于循环垃圾回收器的正常操作。

唯一的行为文档是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). */ 

请注意,将值设置为“ None是一个优化; 替代方法是从映射中删除名称,这会导致不同的错误(当尝试使用__del__处理程序中的全局variables时,会导致不同的错误( NameErrorexception而不是AttributeError )。

正如你在邮件列表中发现的那样,行为早于循环垃圾收集器; 它在1998年被增加了 ,而循环垃圾收集器在2000年被增加了 。 由于函数对象总是引用模块__dict__模块中的所有函数对象都涉及到循环引用,所以在GC进场之前__dict__需要清除。

即使在添加循环GC时也保持原位,因为可能有循环中涉及__del__方法的对象。 这些不是垃圾收集 ,清理模块字典将至less从这样的周期中删除模块__dict__ 。 不这样做将保持该模块的所有引用的全局variables。

现在对PEP 442进行的更改使垃圾收集器可以清除带有__del__终结器的对象的循环引用, 在大多数情况下 ,无需清除模块__dict__ 。 代码仍然存在,但只有在__dict__属性仍然存在时才会触发,即使将sys.modules的内容移动到弱引用并在解释器closures时启动GC集合运行, 模块终结器简单地减less它们的引用计数。

在线程文档底部有一小部分相关的文档 :

其次,在解释者开始closures之前,所有的input尝试都必须完成。 不遵守这一限制将导致解释器closures期间的间歇性exception和崩溃(因为延迟import试图访问不再处于有效状态的机器)。