2017-11-15 3 views
2
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はリークしますか?

ただし、インデントなしのjson.dumps(self.__dict__)では、リークは観察されません。

更新:問題を浮き彫りにするコードが簡略化されています。

答えて

1

REF:https://bugs.python.org/issue32045

indent=TrueはちょうどPython実装の代わりに、C実装を使用してJSONます。 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コレクタが到達不能であることが判明したオブジェクトのリストですが、解放できませんでしたが、解放できませんでした。

iが仮定:

  • 循環参照が到達不能であるが、解放され、従って、収集可能することができます。
  • __del__ファイナライザ(循環参照付き)オブジェクトに到達できないため解放できないため、回収できません。
関連する問題