2011-07-18 3 views
5

Pythonで作業する私は、キューから読み取り、キューから読み取られたレコードのXMLタグのいくつかに基づいて辞書を作成し、この辞書を返す関数を持っています。私はループ内でこの関数を永遠に呼び出します。辞書は毎回再割り当てされます。辞書によって以前に使用されたメモリは、それぞれの再割り当て時に解放されるのか、それとも孤立して最終的にメモリの問題を引き起こすのでしょうか?再割り当てすると、Python辞書はすべてのメモリを解放しますか?

def readq(): 
    qtags = {} 
    # Omitted code to read the queue record, get XML string, DOMify it 

    qtags['result'] = "Success" 
    qtags['call_offer_time'] = get_node_value_by_name(audio_dom, 'call_offer_time') 
    # More omitted code to extract the rest of the tags 

    return qtags 

while signals.sigterm_caught == False: 
    tags = readq() 
    if tags['result'] == "Empty": 
     time.sleep(SLEEP_TIME) 
     continue 
    # Do stuff with the tags 

したがって、ループのたびにタグを再割り当てすると、以前の割り当てで使用されたメモリが解放されてから、新しい割り当てによって割り当てられますか?

+0

明示的にクリアするためにループの最後に "del tags"を追加するとどうなりますか? – codebunny

+0

何が起こっているのかを明確にしてくれたことに感謝します。 – codebunny

答えて

8

実行時に言語実装の知識から証明された場合、オブジェクトのメモリは解放され、ガベージコレクタはコレクションを作成するのに適しているとみなします。それは絶対最小ですが、あなたはもはや想定してはいけません。そして、あなたは通常、には何もないと心配する必要があります

事実上、それが最後の参照間の時間に一部時点で解放することができる言えばもっと(「参照」はスコープ内の名前に限定されるものではなく、オブジェクトreachableが作る何もすることができます)が除去されているとメモリが不足しています。あなたのコードを実行しているPythonの実装で解放する必要はありません。それは、メモリのクリーニングをOSに任せて、ファイナライザなどを忘れるかもしれません。前回の参照の終了と実際のメモリの使用の間には、顕著な遅延があることに注意してください。しかし、前述したように、収集するゴミがあれば、大量のメモリ使用を避けるために、ほとんどの実装は途絶えてしまいます。

実際にはCPython(リファレンス実装)上で実行していますが、これは常に使用されており、ほとんどの場合、常に循環参照を扱うために実際のGCで拡張された参照カウントを使用します。巡回参照(比較的まれで、コードにはそれがあるようには見えませんが、たとえばグラフのような構造で発生する可能性があります)、最後の参照が削除/上書きされるとすぐに解放されます。もちろん、他の実装はそれほど予測できません。PyPyだけで6つの異なるガベージコレクタがありますが、すべてが上記の段落に該当します。

+0

+1素敵で完全な答えです。 –

2

いいえ、新しいオブジェクトが作成された後に解放されます。

古いオブジェクトを参照カウントにするには、tagsを新しいオブジェクトにポイントする必要があります。これはreadqが返された後に発生するため、少なくともqtags = {}の先頭からtags = readq()の後に両方のオブジェクトが存在します。

@delnanがtagsは、新しいオブジェクトに指摘されたすぐ後に、上述したように、古いものは、それへの参照がなくなったとして、ガベージコレクタによって解放されません。

+0

実際、@ delnanが述べているように、特定の実装を想定できない限り、オブジェクトは「すぐに」収集する必要はありません。 –

+0

私は理解していますが、ポスターはその記憶が解放されているかどうかを尋ねなければならなかったので、「すぐに」真実の良い近似です。 – agf

1

通常、Pythonはあなたが投げるものに追いつくことができます。 Pythonで使用されるガーベッジコレクタは参照カウントを使用するため、メモリ使用量はほぼ一定である必要があります。メモリ内のスパイクは表示されません。参照を削除すると(変数を別のものに代入すると)、ガベージコレクタはメモリを「ヒープ」に戻します。だからメモリについて心配しないでください。私は数時間にわたり変数を書き直すためのテストを行っているシミュレータを実行しましたが、メモリ使用量はほぼ同じです。新しい辞書を割り当てると解放されます。

関連する問題