我正在开发一个将文件(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)
请注意:我已经反对使用解析文件中的文本来更早地创建类,但显然他们已经开始在这里使用它并看到我没有的一些好处,所以远离这个解决方案是没有'现在可行。
答案 0 :(得分:1)
我认为GC可以处理循环引用,但是您需要做的是从globals()dict中删除引用:
try:
del globals()['DummyA']
except KeyError:
pass
否则会有一个非循环引用类对象,它将阻止它被清理。
答案 1 :(得分: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