gpt4 book ai didi

python - Python模块是否曾经被垃圾收集?

转载 作者:行者123 更新时间:2023-12-05 01:17:42 24 4
gpt4 key购买 nike

如果我在 Python 中加载一个模块,它会被垃圾回收吗?构建这个问题的另一种方法是,Python 在哪里保存对 Python 模块的引用?正如我假设的那样,如果不再有任何引用,垃圾收集器将删除一个模块。

这是我在 Python 解释器中尝试的示例:

>>> from importlib import import_module
>>> import sys
>>> import gc

>>> x = import_module('math')
>>> 'math' in sys.modules

这个输出:

True

所以让我们删除脚本中对模块的引用。

>>> del x
>>> gc.collect()
>>> 'math' in sys.modules

Python 仍然跟踪数学模块,因为输出仍然是:

True

但现在如果我从 sys.modules 中删除数学,我将不再知道任何进一步的引用:

>>> del sys.modules['math']
>>> gc.collect()

但是,gc.collect() 的输出是:

0

没有垃圾回收,因此该模块不再位于 sys.modules 或我的脚本中。为什么没有垃圾回收?

最佳答案

一般来说,至少在 3.4 及以后的版本中,模块对象在这方面应该没有什么特别之处。当然,在 sys.modules 中通常会有对每个加载模块的引用,但如果您明确删除了它,那么模块应该能够消失。

话虽这么说,过去肯定存在一些问题阻止了这种情况在某些情况下发生,我不保证从 3.7 开始就没有任何此类问题。

不幸的是,您的测试实际上并没有测试任何东西。假设您正在使用 CPython。在 CPython 中,垃圾收集器使用引用计数——它直接在每个对象上存储一个计数,每次绑定(bind)一个新名称时递增和递减计数,如果计数变为 0 则立即删除它。中的东西>gc 模块是一个循环收集器,需要它来处理一些特殊情况,即两个(或多个)对象相互引用但没有其他人引用它们。如果该模块不是这样一个循环的一部分,它会在您调用 gc.collect() 之前被删除,因此当然会返回 0。但是 0 什么也没告诉您。

您的测试还有其他问题。

首先,您不应该在交互式解释器中测试垃圾。各种额外的东西都以难以解释的方式保存在那里。最好写个测试脚本。

其次,你不应该使用 math 作为你的测试。它是一个扩展模块(即用 C 而不是 Python 编写),即使在 3.5 中进行了重大更改后,它们仍然无法正常工作。它也是一个核心模块,可能是启动的一部分或解释器的其他部分需要的,即使您没有从您的代码中引用它。所以,最好使用其他东西。

无论如何,我认为可能有一种方法可以直接测试它,而无需使用调试器,但无法保证它是否有效。

首先,您需要创建一个 types.ModuleType 的子类,它有一个 __del__ 方法来打印一些消息。然后,您只需要导入一个模块(一个 .py 模块,而不是扩展模块)并将其 __class__ 设置为该子类。这可能与 .py 文件中的 __class__ = MyModuleSubclass 一样简单。现在,当它被收集时,它的析构函数将运行,并且您将获得它已被收集的证据。 (好吧,除非析构函数恢复它,否则证明它已被收集,但如果你的析构函数除了打印静态字符串之外什么都不做,希望这不是一个担心。)

关于python - Python模块是否曾经被垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49150115/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com