【问题标题】:Where is Python's shutdown procedure setting module globals to None documented?Python 的关闭过程设置模块全局变量在哪里记录?
【发布时间】:2014-10-28 06:29:15
【问题描述】:

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

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

[...] 显着减少将经历“模块全局设置为无”行为的模块数量,该行为用于故意中断循环并尝试干净地释放更多外部资源。

SO questions about this behaviourC API documentation mentions shutdown behaviour for embedded interpreters

我还找到了related thread on python-devrelated CPython bug

这个补丁不会改变模块的行为 对象尽快清除其全局字典 它们已被释放。

这种行为记录在哪里?它是特定于 Python 2 的吗?

【问题讨论】:

    标签: python multithreading python-2.7 python-internals


    【解决方案1】:

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

    作为此更改的一部分,在大多数情况下,在解释器关闭期间模块全局变量不再强制设置为 None,而是依赖于循环垃圾收集器的正常操作。

    该行为的唯一文档是moduleobject.c source code

    /* 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 是一种优化;另一种方法是从映射中删除名称,这将导致不同的错误(NameError 异常而不是 AttributeErrors 在尝试使用来自 __del__ 处理程序的全局变量时)。

    正如您在邮件列表中发现的那样,这种行为早于循环垃圾收集器;它是added in 1998,而循环垃圾收集器是added in 2000。由于函数对象总是引用模块__dict__,模块中的所有函数对象都涉及循环引用,这就是为什么__dict__需要在GC之前清除。

    即使添加了循环 GC,它也会保留在原位,因为循环中可能存在具有 __del__ 方法的对象。这些aren't otherwise garbage-collectable 和清除模块字典至少会从此类循环中删除模块__dict__。不这样做将使该模块的 所有 引用的全局变量保持活动状态。

    PEP 442 所做的更改现在使垃圾收集器可以清除带有提供__del__ 终结器的对象的循环引用,从而无需清除模块__dict__ 在大多数情况下时间>。代码为still there,但仅当__dict__ 属性仍然存在时才会触发,即使在将sys.modules 的内容移动到弱引用并在解释器关闭时启动GC 收集运行之后;模块终结器只是减少它们的引用计数。

    【讨论】:

      【解决方案2】:

      bottom of the threading docs有少量相关文档:

      其次,必须在解释器开始自行关闭之前完成所有导入尝试。 [..] 不遵守此限制将导致解释器关闭期间出现间歇性异常和崩溃(因为后期导入尝试访问不再处于有效状态的机器)。

      【讨论】:

        猜你喜欢
        • 2020-03-06
        • 1970-01-01
        • 2011-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-29
        • 2013-02-21
        • 2013-05-25
        相关资源
        最近更新 更多