python-python內存泄露跟蹤

最近被python的內存使用搞得比較的鬱悶,記錄在案。python

 

內存泄漏的經典定義是曾經使用過一次的內存,如今卻沒有,但尚未被回收。使用純Python代碼幾乎不可能。但正如Antoine指出的那樣,即便您不須要保留全部數據,您也能夠經過容許數據結構無限制地增加來輕鬆地消耗全部內存。程序員

1 將值存儲在類或全局範圍而不是實例範圍中,而不是實現它。

好比下面的這個代碼:數據結構

class Money(object):
    name = ''
    symbols = []   # This is the dangerous line here

    def set_name(self, name):
        self.name = name

    def add_symbol(self, symbol):
        self.symbols.append(symbol)


m = Money()
m.set_name('Dollar')
m.add_symbol('$')

那麼正確的寫法應該是如何呢?app

class Money(object):
    self.name = ''
    self.symbols = []   # This is the dangerous line here

    def set_name(self, name):
        self.name = name

    def add_symbol(self, symbol):
        self.symbols.append(symbol)

2 sys.exc_info()帶來的循環引用

問題代碼以下:socket

while game.running():
    try:
        key_press = handle_input()
    except SomeException:
        etype, evalue, tb = sys.exc_info()
        # Do something with tb like inspecting or printing the traceback

這裏面咱們可能認爲tb是一個臨時變量,可是實際上,tb包含了handle_input運行的上下文信息。若是game一直在執行中,那麼tb依然不會被釋放,哪怕是下一次執行handle_input。函數

3 在類中本身實現__del__方法

class ClientConnection(...):
    def __del__(self):
        if self.socket is not None:
            self.socket.close()
            self.socket = None
如今這個工做正常,你可能會認爲它是操做系統資源的良好管理者,以確保套接字被「處置」。

可是,若是ClientConnection保留引用說明,用戶和用戶保留對鏈接的引用,您可能會想要說清理時,讓用戶取消引用鏈接。這其實是一個缺陷:循環GC不知道正確的操做順序,也沒法清理它。

對此的解決方案是確保你經過調用某種類型的關閉來斷開事件,可是將該方法命名爲__del__之外的其餘方法。

4 非正常使用C庫

 

在Python中,您相信垃圾收集器會丟棄您不使用的內容。可是,若是使用包裝C庫的C擴展,則大多數時候您負責確保明確關閉或取消分配資源。大多數狀況下都記錄了這一點,可是習慣於沒必要進行此顯式取消分配的python程序員可能會丟棄句柄(如從函數或其餘任何內容返回)到該庫而不知道資源被保留。操作系統

 

 

 

 

 

【參考文獻】code

【1】https://stackoverflow.com/questions/2017381/is-it-possible-to-have-an-actual-memory-leak-in-python-because-of-your-code事件