2010-07-30 87 views
6

我正在打擊一個Python項目中的內存泄漏,並且已經花費了很多時間。我已經將這個問題推演爲一個小例子。現在好像我知道解決方案,但我不明白爲什麼爲什麼python list slice分配會消耗內存?

import random 

def main(): 
    d = {} 
    used_keys = [] 
    n = 0 
    while True: 
     # choose a key unique enough among used previously 
     key = random.randint(0, 2 ** 60) 
     d[key] = 1234 # the value doesn't matter 
     used_keys.append(key) 
     n += 1 
     if n % 1000 == 0: 
      # clean up every 1000 iterations 
      print 'thousand' 
      for key in used_keys: 
       del d[key] 
       used_keys[:] = [] 
       #used_keys = [] 

if __name__ == '__main__': 
    main() 

的想法是,我存儲在字典d一些價值觀和記憶使用的密鑰列表中,以便能夠清潔字典不時。

該程序的這種變化自信地消耗內存從不返回它。如果我使用替代方法來「清除」used_keys這個例子中的評論,一切都很好:內存消耗保持在恆定的水平。

爲什麼?

測試CPython和許多linuxes。

+0

你怎麼知道它肯定永遠不會返回它?這可能只是因爲操作系統從不要求它回來。 – detly 2010-07-30 08:25:23

+2

不應該清除'used_keys'在'used_keys'循環中的鍵之外? – adamk 2010-07-30 08:27:13

+2

>我的想法是,我在dict d中存儲了一些值,並在列表中記憶使用的鍵以便能夠不時地清理字典。 爲什麼不使用'd.keys()'?它將是相同的密鑰列表。 – 2010-07-30 08:28:53

回答

5

這是原因 - 當前方法不會從字典中刪除鍵(實際上只有一個)。這是因爲您在循環中清除了used_keys列表,並且循環過早退出。

然而,第二個(註釋)方法在向used_keys分配新值時起作用,因此循環成功完成。

見的區別:

>>> a=[1,2,3] 
>>> for x in a: 
... print x 
... a=[] 
... 
1 
2 
3 

>>> a=[1,2,3] 
>>> for x in a: 
... print x 
... a[:] = [] 
... 
1 
>>> 
+1

啊!我愚蠢,愚蠢,愚蠢。我很高興重新編寫了一小段代碼中的內存泄漏......當然,這是一個可悲的錯誤。這並不代表我的問題,我會繼續狩獵。但你對原始問題的回答是正確的。謝謝! – nkrkv 2010-07-30 08:41:14

0

爲什麼不這樣的工作?

from itertools import count 
import uuid 

def main(): 
    d = {} 
    for n in count(1): 
     # choose a key unique enough among used previously 
     key = uuid.uuid1() 
     d[key] = 1234 # the value doesn't matter 
     if n % 1000 == 0: 
      # clean up every 1000 iterations 
      print 'thousand' 
      d.clear() 

if __name__ == '__main__': 
    main()