Python的关闭程序记录在哪里?

Wil*_*hes 47 python multithreading python-2.7 python-internals

CPython有一个奇怪的行为,它在关机期间将模块设置为None.在我写完的一些多线程代码关闭期间,这会搞砸错误记录.

我找不到任何有关此行为的文档.它在PEP 432中提到:

[...]显着减少将遇到"模块全局设置为无"行为的模块数量,该行为用于审议中断周期并尝试干净地释放更多外部资源.

有SO有关此问题的提问和C API文档中提到的嵌入式翻译关闭行为.

我还在python-dev和相关的CPython bug 上找到了一个相关的线程:

一旦解除分配,此修补程序不会更改模块对象清除其全局字典的行为.

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

Mar*_*ers 59

行为没有很好地记录,并且从大约1.5-ish 到Python 3.4存在于所有版本的Python中:

作为此更改的一部分,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). */
Run Code Online (Sandbox Code Playgroud)

请注意,将值设置None为优化; 另一种方法是从映射中删除名称,这会导致不同的错误(NameError异常而不是AttributeError在尝试使用__del__处理程序中的全局变量时的s ).

正如您在邮件列表中发现的那样,行为早于循环垃圾收集器; 它于1998年增加,而循环垃圾收集器于2000年增加.由于函数对象总是引用模块,因此模块中的__dict__所有函数对象都涉及循环引用,这就是__dict__GC之前需要清除的原因.

即使添加了循环GC,它也会保留在原位,因为可能存在__del__循环中涉及方法的对象.这些不是垃圾收集的,清理模块字典至少会__dict__从这样的循环中移除模块.不这样做会使该模块的所有引用的全局变量保持活动状态.

现在,对PEP 442所做的更改使垃圾收集器可以使用提供__del__终结器的对象清除循环引用,从而无需在__dict__ 大多数情况下清除模块.代码仍然存在,但只有__dict__在将内容移动sys.modules到弱引用并且在解释器关闭时启动GC集合时,属性仍处于活动状态时才会触发此代码; 模块终结器只是减少它们的引用计数.