1

我正在开发一个将文件(hfd5 - pytables)加载到对象结构中的库。用于结构的实际类作为字符串从 hdf5 文件加载,然后以这种方式加载:

class NamespaceHolder(dict):
    # stmt is the source code holding all the class defs
    def execute(self, stmt):
        exec stmt in self

问题是,像这样加载多个类会导致对象出现在垃圾收集的不可回收部分,即实际的类定义中。我也可以将它加载到全局字典中,但问题仍然存在于孤立类中。有什么办法可以卸载类吗?

主要问题是班级。mro属性,其中包含对类本身的引用,导致垃圾收集器无法处理的循环引用。

这是一个小测试用例,供您自己查看:

import gc

if __name__ == "__main__":
    gc.enable()
    gc.set_debug(gc.DEBUG_LEAK)

    code = """
class DummyA(object):
    pass
"""
    context = {}

    exec code in context
    exec code in context

    gc.collect()
    print len(gc.garbage)

请注意:我之前已经反对使用解析文件中的文本来创建类,但显然他们在这里使用它并且看到了一些我没有看到的好处,所以现在放弃这个解决方案是不可行的.

4

2 回答 2

1

我认为 GC 可以处理循环引用,但是您需要做的是从 globals() 字典中删除引用:

try:
    del globals()['DummyA']
except KeyError:
    pass

否则会有一个对类对象的非循环引用,这将阻止它被清理。

于 2009-05-28T09:37:32.400 回答
1

gc.set_debug(gc.DEBUG_LEAK) 导致泄漏。试试这个:

import gc

def foo():                              
    code = """
class DummyA(object):
    pass             
"""
    context = {}
    exec code in context
    exec code in context

    gc.collect()
    print len(gc.garbage), len(gc.get_objects())

gc.enable()
foo(); foo() # amount of objects doesn't increase
gc.set_debug(gc.DEBUG_LEAK)
foo() # leaks
于 2009-05-28T12:07:44.750 回答