2009-05-28 13 views
1

ファイル(hfd5 - pytables)をオブジェクト構造体にロードするライブラリで作業しています。構造のために使用されている実際のクラスは、HDF5ファイルから文字列としてロードされ、その後、 は、この方法でロードされた:Pythonで、生成されたクラスをアンロードする方法

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) 

だけのノート:私はすでに以前のクラスを作成するためのファイルのテキストをオフ解析する使用しないことを主張してきたが、どうやら彼らは使用して設定されていますここで私がしないいくつかの利点を見て、このソリューションから離れて行くことは現実的ではありません。私は、GCが循環参照に対処することができる、しかし、あなたがする必要があると思う

+0

実際、この非解決策から離れることは常に可能です。回収できないゴミでメモリがクラッタすると、動作していません。 –

+0

私はどこかで(comp.lang.python?Python-Devのリスト?どこで覚えていないのですか?)コアの開発チームがクラスオブジェクトを収集できないということをよく知っていることを覚えています。IIRC Guidoは、あなたのコードに何千ものクラスを動的に作成していますが、あなたのアルゴリズムには何か問題がありますが、ICBWです。 – tzot

答えて

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 
+0

ありがとうございます。私はgc.DEBUG_LEAKをオフにしたときに私のリークがすべて消えてしまったことに気付きました – Staale

1

はグローバル()辞書からの参照を削除します:

try: 
    del globals()['DummyA'] 
except KeyError: 
    pass 

そうでない場合に非円形の参照が存在しますクラスオブジェクトはクリーンアップを停止します。

+0

http://stackoverflow.staale.org/919924.pngをご覧ください これは上記のコードを実行することから来る循環グラフです。ここに含まれるタプルには(DummyA、object)が含まれているため、削除や変更ができないため、DummyAクラスは収集できません – Staale