json.dumps泄漏了吗?

时间:2017-11-15 13:48:15

标签: python json memory-leaks

import gc, json

class leak(object):
    def __init__(self):
        pass

gc.set_debug(gc.DEBUG_LEAK)
while True:
    leak_ = leak()
    json.dumps(leak_.__dict__, indent=True)
    gc.collect()
    print(f"garbage count: {len(gc.garbage)}")

在Python 3.6.3下使用以下代码,垃圾计数不断增加,任务管理器记录稳定内存增加。

但是没有缩进json.dumps(self.__dict__),没有发现泄漏。

更新:简化了代码以突出显示问题。

1 个答案:

答案 0 :(得分:1)

参考:https://bugs.python.org/issue32045

indent=True只是让json使用Python实现而不是C实现。 Python实现使用相互引用的闭包。不涉及json的简单示例是:

import gc

def f():
    def g():
        return h
    def h():
        return g
    return

gc.set_debug(gc.DEBUG_LEAK)
while True:
    f()
    gc.collect()
    print(f"garbage count: {len(gc.garbage)}")

使用gc.set_debug(gc.DEBUG_LEAK)导致“泄漏”。 gc.DEBUG_LEAK包括gc.DEBUG_COLLECTABLE,gc.DEBUG_UNCOLLECTABLE和gc.DEBUG_SAVEALL。

gc.DEBUG_SAVEALL导致垃圾收集对象保存在gc.garbage中以供检查。在正常情况下,他们被收集。

我的回复:

你是对的。我意识到后来我实际上在一个com实例化对象中有泄漏,假设它是python中的泄漏并试图使用gc模块找到它。

gc文档让我走上了花园小径。

  

gc.garbage收集器发现的对象列表   无法访问但无法释放(无法收集的对象)。

我假设:

  • 循环引用无法访问,但可以释放,因此可以收集。
  • __del__终结器(带有循环引用?)对象无法访问,无法释放,因此无法收集。