6 Stimmen

Warum Python Liste Slice Zuordnung frisst Speicher?

Ich kämpfe mit einem Speicherleck in einem Python-Projekt und habe schon viel Zeit damit verbracht. Ich habe das Problem auf ein kleines Beispiel zurückgeführt. Jetzt scheine ich die Lösung zu kennen, aber ich kann nicht verstehen なぜ .

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

Die Idee ist, dass ich einige Werte in dem Diktat d und merken Sie sich die benutzten Tasten in einer Liste, um das Diktat von Zeit zu Zeit reinigen zu können.

Diese Variante des Programms frisst munter Speicher und gibt ihn nicht wieder zurück. Wenn ich eine alternative Methode zum "Löschen" verwende used_keys die im Beispiel kommentiert ist, ist alles in Ordnung: Der Speicherverbrauch bleibt konstant.

Warum?

Getestet auf CPython und vielen Linuxen.

5voto

adamk Punkte 42476

Hier ist der Grund - die aktuelle Methode löscht nicht die Schlüssel aus dem Diktat (nur einen, tatsächlich). Das liegt daran, dass Sie die used_keys Liste während der Schleife, und die Schleife wird vorzeitig beendet.

Die 2. (kommentierte) Methode funktioniert jedoch, da Sie einen neuen Wert zuweisen used_keys damit die Schleife erfolgreich beendet wird.

Sehen Sie den Unterschied zwischen:

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

y

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

0voto

John La Rooy Punkte 278961

Warum sollte so etwas nicht funktionieren?

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X