在python中,如何卸载生成的类

在python中,如何卸载生成的类,python,dynamic,garbage-collection,classloader,Python,Dynamic,Garbage Collection,Classloader,我正在开发一个将文件(hfd5-pytables)加载到对象结构中的库。用于结构的实际类作为字符串从hdf5文件加载,然后 以这种方式加载: class NamespaceHolder(dict): # stmt is the source code holding all the class defs def execute(self, stmt): exec stmt in self 问题是,像这样加载多个类会导致对象出现在垃圾收集的不可收集部分,即实际的类

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

class NamespaceHolder(dict):
    # stmt is the source code holding all the class defs
    def execute(self, stmt):
        exec stmt in self
问题是,像这样加载多个类会导致对象出现在垃圾收集的不可收集部分,即实际的类定义中。我也可以将其加载到全局字典中,但问题仍然是孤立类。有没有办法卸载这些类

主要问题是class.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)

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

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

否则,将有一个对类对象的非循环引用,该引用将停止清理该类对象。

gc.set\u debug(gc.debug\u 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

看看这是运行上述代码得到的循环图。这里引用的元组包含(DummyA,object),不能删除或更改,因此DummyA类实际上不能被收集,离开这个非解决方案总是可行的。IIRC Guido说,如果它在内存中塞满了无法收集的垃圾,那么它就不工作了。我记得在某个地方读过(comp.lang.python?python开发列表?不记得在哪里),核心开发团队非常清楚类对象无法收集的事实“如果您在代码中动态创建数千个类,那么您的算法可能有问题”,但是ICBW。非常感谢。但是,我确实注意到,当我关闭gc.DEBUG\u 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