In einem Skript, mit dem ich viele Figuren erstelle fix, ax = plt.subplots(...)
, wird die Warnung RuntimeWarning angezeigt: Es wurden mehr als 20 Figuren geöffnet. Über die Pyplot-Schnittstelle ( matplotlib.pyplot.figure
) erstellte Zahlen bleiben bis zum expliziten Schließen erhalten und verbrauchen möglicherweise zu viel Speicher.
Ich verstehe jedoch nicht, warum ich diese Warnung erhalte, da fig.savefig(...)
ich sie nach dem Speichern mit lösche fig.clear(); del fig
. Zu keinem Zeitpunkt in meinem Code ist mehr als eine Figur gleichzeitig geöffnet. Trotzdem bekomme ich die Warnung vor zu vielen offenen Zahlen. Was bedeutet das / wie kann ich die Warnung vermeiden?
python
python-3.x
matplotlib
andreas-h
quelle
quelle
plt
. ZB stackoverflow.com/a/16337909/325565 (Nicht um eine meiner eigenen Antworten zu stecken , aber es ist die, die ich am schnellsten finden konnte ...)Antworten:
Verwenden Sie
.clf
oder.cla
auf Ihrem Figurenobjekt, anstatt eine neue Figur zu erstellen . Von @DavidZwickerAngenommen, Sie haben
pyplot
als importiertplt.cla()
löscht eine Achse , dh die aktuell aktive Achse in der aktuellen Abbildung. Die anderen Achsen bleiben unberührt.plt.clf()
Löscht die gesamte aktuelle Figur mit all ihren Achsen, lässt jedoch das Fenster geöffnet, sodass es für andere Diagramme wiederverwendet werden kann.plt.close()
schließt ein Fenster , das das aktuelle Fenster ist, sofern nicht anders angegeben.plt.close('all')
schließt alle offenen Figuren.Der Grund,
del fig
der nicht funktioniert, ist, dass diepyplot
Zustandsmaschine einen Verweis auf die herumliegende Figur behält (wie es sein muss, wenn sie wissen will, was die 'aktuelle Figur' ist). Dies bedeutet, dass selbst wenn Sie Ihren Verweis auf die Figur löschen , mindestens ein Live-Verweis vorhanden ist , sodass niemals Müll gesammelt wird.Da ich hier nach der kollektiven Weisheit für diese Antwort frage, erwähnt @JoeKington in den Kommentaren, dass
plt.close(fig)
eine bestimmte Figureninstanz aus der Pylab-Zustandsmaschine ( plt._pylab_helpers.Gcf ) entfernt und das Sammeln von Müll ermöglicht wird.quelle
clf
für diefigure
Klasse, aber nichtclose
. Warum wirddel fig
die Figur nicht geschlossen und gelöscht?close
Figurenobjekt nicht funktioniert, nennen Sie es wieplt.close()
stattfig.clf()
.del fig
funktioniert dies nicht, weil die Angabe einer__del__
Methode (die im Grunde genommen aufgerufenplt.close(fig)
würde) in diesem speziellen Fall zu Zirkelverweisen führen würde undfig
eine__del__
andere Methode dazu führen würde, dass andere Dinge nicht als Müll gesammelt werden . (Oder das ist sowieso meine vage Erinnerung.) Auf jeden Fall ist es ein bisschen nervig, aber Sie solltenplt.close(fig)
stattdessen anrufendel fig
. Nebenbei bemerkt, Matplotlib könnte wirklich einen Kontextmanager dafür verwenden ...plt.close(fig)
wird, dass eine bestimmte Figureninstanz von der Pylab-Zustandsmaschine (plt._pylab_helpers.Gcf
) entfernt und das Sammeln von Müll ermöglicht wird.plt
ist ein bisschen chaotisch und es gibt Gedanken darüber, wie man ein paar davon noch einmal macht. Der Kontextmanager ist faszinierend ... Siehe github.com/matplotlib/matplotlib/pull/2736 , github.com/matplotlib/matplotlib/pull/2624Hier ist ein bisschen mehr Detail, um die Antwort von Hooked zu erweitern . Als ich diese Antwort zum ersten Mal las, habe ich die Anweisung zum Anrufen verpasst,
clf()
anstatt eine neue Figur zu erstellen .clf()
allein hilft nicht, wenn Sie dann gehen und eine andere Figur erstellen.Hier ist ein triviales Beispiel, das die Warnung verursacht:
Um die Warnung zu vermeiden, muss ich den Anruf
subplots()
außerhalb der Schleife ziehen. Um die Rechtecke zu halten sehen, muss ich Schalterclf()
aufcla()
. Dadurch wird die Achse gelöscht, ohne die Achse selbst zu entfernen.Wenn Sie Diagramme in Stapeln erstellen, müssen Sie möglicherweise beide
cla()
und verwendenclose()
. Ich stieß auf ein Problem, bei dem eine Charge mehr als 20 Parzellen haben konnte, ohne sich zu beschweren, aber sie beschwerte sich nach 20 Chargen. Ich habe das behoben, indem ichcla()
nach jedem Plot undclose()
nach jeder Charge verwendet habe.Ich habe die Leistung gemessen, um festzustellen, ob es sich lohnt, die Zahl innerhalb eines Stapels wiederzuverwenden, und dieses kleine Beispielprogramm verlangsamte sich von 41 auf 49 Sekunden (20% langsamer), als ich gerade
close()
nach jedem Plot anrief.quelle
Wenn Sie wissentlich viele Diagramme im Speicher behalten möchten, aber nicht gewarnt werden möchten, können Sie Ihre Optionen aktualisieren, bevor Sie Zahlen generieren.
Dadurch wird verhindert, dass die Warnung ausgegeben wird, ohne dass Änderungen an der Art und Weise vorgenommen werden, wie der Speicher verwaltet wird.
quelle
Das folgende Snippet hat das Problem für mich gelöst:
Wenn
_wrapped_figure
der Gültigkeitsbereich überschritten wird, ruft die Laufzeit unsere__del__()
Methode mitplt.close()
inside auf. Dies geschieht auch dann, wenn eine Ausnahme nach dem_wrapped_figure
Konstruktor ausgelöst wird .quelle
Dies ist auch nützlich, wenn Sie die Warnung nur vorübergehend unterdrücken möchten:
quelle