webentwicklung-frage-antwort-db.com.de

Python-Müllsammlung

Ich habe einen Python-Code erstellt, der ein Objekt in einer Schleife erstellt, und in jeder Iteration dieses Objekt mit einem neuen Typ desselben Typs überschrieben. Dies wird 10.000 Mal ausgeführt, und Python benötigt jede Sekunde 7 MB Speicher, bis mein 3 GB RAM verwendet wird. Kennt jemand eine Möglichkeit, die Objekte aus dem Speicher zu entfernen?

35
utdiscant

Sie haben nicht genügend Informationen zur Verfügung gestellt - dies hängt von den Besonderheiten des Objekts ab, das Sie erstellen, und davon, was Sie sonst noch mit dem Objekt in der Schleife tun. Wenn das Objekt keine Zirkelverweise erstellt, sollte es bei der nächsten Iteration freigegeben werden. Zum Beispiel der Code

for x in range(100000):
  obj = " " * 10000000

führt nicht zu einer ständig zunehmenden Speicherzuordnung.

19
Vinay Sajip

Ich denke, dass dies ein Zirkelverweis ist (obwohl die Frage zu diesen Informationen nicht explizit ist).

Eine Möglichkeit, dieses Problem zu lösen, besteht darin, die Garbage Collection manuell aufzurufen. Wenn Sie den Garbage Collector manuell ausführen, werden kreisförmige Objekte ebenfalls durchlaufen.

import gc

for i in xrange(10000):
    j = myObj()
    processObj(j)
    #assuming count reference is not zero but still
    #object won't remain usable after the iteration

    if !(i%100):
        gc.collect()

Führen Sie den Garbage Collector hier nicht zu oft aus, da er einen eigenen Overhead hat, z. Wenn Sie in jeder Schleife einen Garbage-Collector ausführen, wird die Interpretation extrem langsam.

23
hasanatkazmi

Dies ist ein alter Fehler, der für einige Typen in Python 2.5 korrigiert wurde. Was geschah, war, dass Python Dinge wie leere Listen/Wörterbücher/tupes/floats/ints nicht so gut sammelte. In Python 2.5 wurde dies meistens behoben. Floats und Ints sind jedoch Singletons für Vergleiche. Wenn also einer davon erstellt wird, bleibt er so lange in der Nähe, wie der Interpreter lebt. Ich bin von diesem schlimmsten Umgang mit einer großen Anzahl von Schwimmern gebissen worden, da sie die unangenehme Angewohnheit haben, einzigartig zu sein. Dies wurde charakterisiert für Python 2.4 und aktualisiert, dass es in Python 2.5 gefaltet wird

Der beste Weg, den ich gefunden habe, ist ein Upgrade auf Python 2.5 oder neuer, um sich um das Problem der Listen/Wörterbücher/Tupel zu kümmern. Für Zahlen ist die einzige Lösung, nicht zu viele Zahlen in Python zu lassen. Ich habe es mit meinem eigenen Wrapper zu einem C++ - Objekt gemacht, aber ich habe den Eindruck, dass numpy.array ähnliche Ergebnisse liefert.

Als Postskriptum habe ich keine Ahnung, was mit Python 3 passiert ist, aber ich habe den Verdacht, dass Zahlen immer noch Teil eines Singleton sind. Der Speicherverlust ist also eigentlich ein Merkmal der Sprache.

13
Pete Peterson

Wenn Sie Zirkelreferenzen erstellen, werden Ihre Objekte nicht sofort freigegeben, sondern müssen warten, bis ein GC-Zyklus ausgeführt wird.

Sie können das Modul weakref verwenden, um dieses Problem zu beheben, oder Ihre Objekte nach der Verwendung explizit löschen.

6
Algorias

Ich fand heraus, dass in meinem Fall (mit Python 2.5.1) mit Zirkelverweisen, die Klassen mit __del__()-Methoden beinhalteten, nicht nur die Speicherbereinigung nicht rechtzeitig stattfand, sondern die __del__()-Methoden meiner Objekte nie aufgerufen wurden, selbst wenn die Skript wurde beendet. Also habe ich weakref verwendet, um die Zirkelverweise zu durchbrechen und alles war gut.

Ein großes Lob an Miles, der alle Informationen in seinen Kommentaren zur Verfügung gestellt hat, damit ich dies zusammenstellen kann.

3
Von

Mit einer der folgenden Möglichkeiten können Sie am REPL eine Dereferenzierung einer Variablen erzwingen:

>>> x = 5
>>> x
5
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
1
Mark Rushakoff

schwachref kann für kreisförmigen, objektstrukturierten Code verwendet werden, wie im erläuterten Beispiel

0
alkanschtein