在python中,如何卸载生成的类
我正在开发一个将文件(hfd5-pytables)加载到对象结构中的库。用于结构的实际类作为字符串从hdf5文件加载,然后 以这种方式加载:在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 问题是,像这样加载多个类会导致对象出现在垃圾收集的不可收集部分,即实际的类
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