【问题标题】:Does json.dumps leak?json.dumps 是否泄漏?
【发布时间】:2018-04-28 18:41:45
【问题描述】:
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__),没有观察到泄漏。

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

【问题讨论】:

    标签: python json memory-leaks


    【解决方案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__ 终结器(带有循环引用?)对象无法访问,无法释放,因此无法回收。

    【讨论】:

    • 那么答案是什么!?
    • json.dumps(leak_.__dict__) 使用 c 实现。 json.dumps(leak_.__dict__, indent=True) 使用python实现。 python实现导致循环引用。如果我们现在使用 gc.set_debug(gc.DEBUG_LEAK) 这些循环引用被保存以供检查,它看起来像一个“泄漏”。
    猜你喜欢
    • 2010-11-25
    • 1970-01-01
    • 2011-01-16
    • 2012-09-13
    • 2020-07-22
    • 2012-11-11
    • 2010-10-13
    • 2019-01-28
    • 2015-02-07
    相关资源
    最近更新 更多