wake-up-neo.com

Python Speicherverluste

Ich habe ein Skript mit langer Laufzeit, das, wenn es lange genug ausgeführt wird, den gesamten Speicher auf meinem System belegt.

Ohne näher auf das Skript einzugehen, habe ich zwei Fragen:

  1. Gibt es irgendwelche "Best Practices", die dazu beitragen, das Auftreten von Lecks zu verhindern?
  2. Welche Techniken gibt es, um Speicherlecks in Python zu beheben?
157
Fragsworth

Schauen Sie sich diesen Artikel an: Tracing python Memory Leaks

Beachten Sie auch, dass im Garbage Collection-Modul tatsächlich Debug-Flags gesetzt sein können. Schaue auf die set_debug Funktion. Schauen Sie sich außerdem dieser Code von Gnibbler an, um die Objekttypen zu bestimmen, die nach einem Aufruf erstellt wurden.

96
ChristopheD

Ich habe die meisten zuvor erwähnten Optionen ausprobiert, aber dieses kleine und intuitive Paket als das beste befunden: pympler

Es ist ganz einfach, Objekte zu verfolgen, die nicht vom Müll gesammelt wurden. Schauen Sie sich dieses kleine Beispiel an:

paket installieren über pip install pympler

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

Die Ausgabe zeigt Ihnen alle hinzugefügten Objekte sowie den von ihnen belegten Speicher.

Beispielausgabe:

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

Dieses Paket bietet eine Reihe weiterer Funktionen. Überprüfen Sie Pymplers Dokumentation , insbesondere den Abschnitt Identifizierung von Speicherlecks .

76
linqu

Lassen Sie mich empfehlen mem_top Tool,
das hat mir geholfen, ein ähnliches Problem zu lösen.

In einem Python Programm werden die häufigsten Verdächtigen für Speicherverluste sofort angezeigt.

22
Denis Ryzhkov

Tracemalloc-Modul wurde als integriertes Modul ab Python 3.4 integriert und ist anscheinend auch für frühere Versionen von Python verfügbar = as eine Drittanbieter-Bibliothek (habe es jedoch nicht getestet).

Dieses Modul kann die genauen Dateien und Zeilen ausgeben, die den meisten Speicher zugewiesen haben. IMHO, diese Information ist unendlich wertvoller als die Anzahl der zugewiesenen Instanzen für jeden Typ (was 99% der Zeit eine Menge Tupel ergibt, was ein Hinweis ist, aber in den meisten Fällen kaum hilft).

Ich empfehle Ihnen, tracemalloc in Kombination mit Pyrasit zu verwenden. Wenn Sie das Top-10-Snippet in einer Pyrasit-Shell 9-mal von 10 ausführen, erhalten Sie genügend Informationen und Hinweise, um das Leck innerhalb von 10 Minuten zu beheben. Wenn Sie die Ursache des Lecks jedoch immer noch nicht finden können, gibt Ihnen Pyrasit-Shell in Kombination mit den anderen in diesem Thread erwähnten Tools wahrscheinlich noch weitere Hinweise. Sie sollten sich auch alle zusätzlichen Hilfsprogramme ansehen, die Pyrasite zur Verfügung stellt (z. B. Memory Viewer).

13
user1527491

Sie sollten sich besonders Ihre globalen oder statischen Daten (Long Living Data) ansehen.

Wenn diese Daten uneingeschränkt wachsen, kann es auch in Python zu Problemen kommen.

Der Garbage Collector kann nur Daten sammeln, auf die nicht mehr verwiesen wird. Ihre statischen Daten können jedoch Datenelemente verbinden, die freigegeben werden sollen.

Ein weiteres Problem können Speicherzyklen sein, aber zumindest in der Theorie sollte der Garbage Collector Zyklen finden und eliminieren - zumindest solange sie nicht auf einige Daten mit langer Lebensdauer angewiesen sind.

Welche Arten von Daten mit langer Lebensdauer sind besonders problematisch? Sehen Sie sich Listen und Wörterbücher genau an - sie können unbegrenzt wachsen. In Wörterbüchern sehen Sie möglicherweise gar keine Probleme, da beim Zugriff auf Dikte die Anzahl der Schlüssel im Wörterbuch für Sie möglicherweise nicht von großer Bedeutung ist ...

11
Juergen

Zum Erkennen und Lokalisieren von Speicherlecks bei lang laufenden Prozessen, z. In Produktionsumgebungen können Sie jetzt stackimpact verwenden. Es wird tracemalloc darunter verwendet. Weitere Infos in dieser Beitrag .

enter image description here

7
logix

Wir sind uns nicht sicher über "Best Practices" für Speicherverluste in Python, aber python sollte seinen eigenen Speicher durch den Garbage Collector löschen. Daher würde ich hauptsächlich nach einer kurzen zirkulären Liste suchen, da sie wird nicht vom Müllmann abgeholt.

4
martiert

Achten Sie bei Best Practices auf rekursive Funktionen. In meinem Fall stieß ich auf Probleme mit der Rekursion (wo es keine geben musste). Ein vereinfachtes Beispiel von dem, was ich tat:

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

wenn Sie auf diese rekursive Weise arbeiten, wird die Garbage Collection nicht ausgelöst und die Reste der Funktion werden gelöscht, sodass die Speichernutzung mit jedem Mal zunimmt.

Meine Lösung bestand darin, den rekursiven Aufruf aus my_function () zu ziehen und main () zu behandeln, wenn er erneut aufgerufen werden soll. Auf diese Weise endet die Funktion auf natürliche Weise und bereinigt sich selbst.

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()
3
The4thIceman

Dies ist keineswegs ein vollständiger Ratschlag. Beim Schreiben mit dem Gedanken, zukünftige Speicherverluste (Schleifen) zu vermeiden, ist jedoch zu beachten, dass alles, was einen Verweis auf einen Rückruf akzeptiert, diesen Rückruf als schwachen Verweis speichern sollte.

3