2009-05-28 55 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) 

只是注意:我已經極力反對使用解析關閉在前面創建的類文件的文本,但顯然他們是在使用設置它在這裏看到我沒有的好處,所以現在離開這個解決方案是不可行的。

+0

實際上,遠離這種非解決方案總是可行的。如果它使用無法收集的垃圾混亂內存,則不起作用。 – 2009-05-28 10:07:00

+0

我記得在某處閱讀(comp.lang.python?Python-Dev列表?不記得在哪裏)核心開發團隊完全瞭解類對象不能被收集的事實,而且IIRC Guido說:「如果你'在您的代碼中動態創建數千個類,您的算法出現問題「,但ICBW。 – tzot 2009-05-28 21:06:45

回答

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 
1

我覺得GC可以循環引用應付,但是你需要做的是從全局刪除引用()字典:

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

否則會出現非圓形參考類對象會阻止它被清理。

+0

看看http://stackoverflow.staale.org/919924.png 這是來自運行上述代碼的循環圖。這裏所指的元組包含(DummyA,object),並且不能被刪除或修改,因此DummyA類不能被收集。 – Staale 2009-05-28 10:05:35