gpt4 book ai didi

python - 重新加载时无法访问gc()

转载 作者:行者123 更新时间:2023-11-28 21:19:00 25 4
gpt4 key购买 nike

我有这段代码,保存为so.py:

import gc
gc.set_debug(gc.DEBUG_STATS|gc.DEBUG_LEAK)

class GUI():
#########################################
def set_func(self):
self.functions = {}
self.functions[100] = self.userInput
#########################################
def userInput(self):
a = 1
g = GUI()
g.set_func()
print gc.collect()
print gc.garbage

这是输出: enter image description here

我有两个问题:

  1. 为什么第一次导入时gc.collect()没有报unreachable?相反,它仅在 reload() 时报告 unreachable

  2. 有什么快速的方法可以修复这个函数映射循环引用,即 self.functions[100] = self.userInput ?因为我的旧项目有很多这个函数映射循环引用,我正在寻找一种快速的方法/一行来更改这些代码。目前我所做的是在最后为所有这些函数“del g.functions”。

最佳答案

  1. 第一次导入模块时,没有收集任何东西,因为您有一个对 so 模块的引用,并且所有其他对象都被它引用,所以它们都是活的,是垃圾收藏家没有什么可收集的。

    当您reload(so) 时,会重新执行该模块,覆盖所有以前的引用,因此现在旧值 不再有任何引用。

    确实在以下方面有引用周期:

     self.functions[100] = self.userInput

    由于 self.userInput 是一个绑定(bind)方法,它引用了 self。所以现在 self 引用了 functions 字典,它引用了 userInput bound 方法,它有一个对 self 的引用和 gc 将收集这些对象。

  2. 这取决于您要做什么。从您的代码中不清楚您如何使用 self.functions 字典,并且取决于不同的选项可能是可行的。

    打破循环的最简单方法是简单地创建self.functions 属性,而是显式地传递字典。

    如果 self.functions 只引用绑定(bind)方法,您可以存储方法的名称而不是方法本身:

    self.functions[100] = self.userInput.__name__

    然后你可以调用这个方法来做:

    getattr(self, self.functions[100])()

    或者你可以这样做:

    from operator import methodcaller
    call_method = methodcaller(self.functions[100])
    call_method(self) # calls self.userInput()

我真的不明白你所说的“目前我所做的是 del g.functions 最后所有这些函数”是什么意思。您指的是哪些功能?

此外,这真的是个问题吗?您遇到真正的内存泄漏吗?

请注意,垃圾收集器将对象报告为无法访问,而不是无法收集。这意味着即使对象是引用循环的一部分,对象也会被释放。所以应该不会发生内存泄漏。

事实上,添加 del g.functions无用的,因为对象无论如何都会被释放,所以一行修复就是简单地删除所有那些 del 语句,因为它们根本不做任何事情。

它们被放入 gc.garbage 的事实是因为 gc.DEBUG_LEAK 暗示了标志 GC.DEBUG_SAVEALL 这使得收集器放所有无法访问的对象都变成了垃圾,而不仅仅是无法收集的对象。

关于python - 重新加载时无法访问gc(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25502347/

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