2010-07-30 12 views
6

Walczę z wyciekiem pamięci w projekcie Pythona i spędziłem na nim wiele czasu. Wydedukowałem problem na mały przykład. Teraz wydaje mi się, że znam rozwiązanie, ale nie mogę zrozumieć, dlaczego.Dlaczego przypisanie plasterka listy Pythona zjada pamięć?

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() 

Chodzi o to, że ja przechowywać niektóre wartości w dict d i zapamiętać używanych klawiszy na liście, aby móc oczyścić dict od czasu do czasu.

Ta odmiana programu pewnie zjada pamięć, nie zwracając jej z powrotem. Jeśli użyję alternatywnej metody "wyczyszczenia" used_keys, która jest skomentowana w przykładzie, wszystko jest w porządku: zużycie pamięci pozostaje na stałym poziomie.

Dlaczego?

Testowane na CPythonie i wielu linuxach.

+0

Skąd wiadomo, że nigdy go nie zwraca? Możliwe, że system operacyjny nigdy go nie prosi. – detly

+2

Czy wyczyszczenie 'used_keys' nie powinno znajdować się poza' 'for key in used_keys' loop? – adamk

+2

> Chodzi o to, że przechowuję pewne wartości w dyktafonie d i zapamiętuję używane klucze na liście, aby od czasu do czasu móc czyścić dyktando. Dlaczego nie używać tylko 'd.keys()'? Będzie to ta sama lista kluczy. –

Odpowiedz

5

Oto powód - obecna metoda nie usuwa kluczy z dyktatury (tylko jeden, faktycznie). Wynika to z wyczyszczenia listy used_keys podczas pętli, a pętla kończy się przedwcześnie.

Druga (skomentowana) metoda działa jednak po przypisaniu nowej wartości do used_keys, aby pętla zakończyła się pomyślnie.

Zobacz różnicę pomiędzy:

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

i

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

Ah !! Jestem głupi, głupi, głupi. Byłem szczęśliwy, mogąc zrekonstruować wyciek pamięci w małym urywku ... Oczywiście, jest to smutny błąd. To nie stanowi mojego problemu, będę kontynuować polowanie. Ale masz rację z odpowiedzią na oryginalne pytanie. Dzięki! – nkrkv

0

Dlaczego nie byłoby coś jak to działa?

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() 
Powiązane problemy