Dans un script où je crée de nombreuses figures avec fix, ax = plt.subplots(...)
, j'obtiens l'avertissement RuntimeWarning: Plus de 20 figures ont été ouvertes. Les figures créées via l'interface pyplot ( matplotlib.pyplot.figure
) sont conservées jusqu'à ce qu'elles soient explicitement fermées et peuvent consommer trop de mémoire.
Cependant, je ne comprends pas pourquoi je reçois cet avertissement, car après avoir enregistré la figure avec fig.savefig(...)
, je la supprime avec fig.clear(); del fig
. À aucun moment de mon code, j'ai plus d'un chiffre ouvert à la fois. Pourtant, je reçois l'avertissement concernant trop de chiffres ouverts. Qu'est-ce que cela signifie / comment puis-je éviter de recevoir l'avertissement?
python
python-3.x
matplotlib
andreas-h
la source
la source
plt
complètement. Par exemple, stackoverflow.com/a/16337909/325565 (Ne pas brancher une de mes propres réponses, mais c'est celle que j'ai pu trouver le plus rapidement ...)Réponses:
Utilisez
.clf
ou.cla
sur votre objet figure au lieu de créer une nouvelle figure. De @DavidZwickerEn supposant que vous ayez importé en
pyplot
tant queplt.cla()
efface un axe , c'est-à-dire l'axe actuellement actif dans la figure actuelle. Il laisse les autres axes intacts.plt.clf()
efface toute la figure actuelle avec tous ses axes, mais laisse la fenêtre ouverte, de sorte qu'elle puisse être réutilisée pour d'autres tracés.plt.close()
ferme une fenêtre , qui sera la fenêtre courante, sauf indication contraire.plt.close('all')
fermera toutes les figures ouvertes.La raison pour laquelle cela
del fig
ne fonctionne pas est que lapyplot
machine à états garde une référence à la figure autour (comme elle doit le faire si elle veut savoir quel est le «chiffre actuel»). Cela signifie que même si vous supprimez votre référence dans la figure, il y a au moins une référence en direct, elle ne sera donc jamais récupérée.Puisque j'interroge ici sur la sagesse collective pour cette réponse, @JoeKington mentionne dans les commentaires qui
plt.close(fig)
supprimera une instance de figure spécifique de la machine à états pylab ( plt._pylab_helpers.Gcf ) et lui permettra d'être ramassé.la source
clf
pour lafigure
classe, mais pasclose
. Pourquoi nedel fig
ferme et ne supprime pas réellement la figure?close
ne fonctionnera pas sur l'objet figure, appelez-le commeplt.close()
, au lieu defig.clf()
.del fig
ne fonctionne pas est que lui donner une__del__
méthode (qui appellerait fondamentalementplt.close(fig)
) finirait par provoquer des références circulaires dans ce cas particulier, etfig
avoir une__del__
méthode empêchera d'autres choses d'être ramassées. . (Ou c'est mon vague souvenir, en tout cas.) En tout cas, c'est certainement un peu ennuyeux, mais vous devriez appelerplt.close(fig)
au lieu dedel fig
. Sur une note latérale, matplotlib pourrait vraiment utiliser un gestionnaire de contexte pour cela ...plt.close(fig)
cela supprimera une instance de figure spécifique de la machine à états pylab (plt._pylab_helpers.Gcf
) et lui permettra d'être récupéré.plt
est un peu en désordre et il y a des idées pour en refaire un tas. Le gestionnaire de contexte est intriguant .... Voir github.com/matplotlib/matplotlib/pull/2736 , github.com/matplotlib/matplotlib/pull/2624Voici un peu plus de détails pour développer la réponse de Hooked . Quand j'ai lu cette réponse pour la première fois, j'ai manqué l'instruction d'appeler
clf()
au lieu de créer une nouvelle figure .clf()
à lui seul, cela n'aide pas si vous allez ensuite créer une autre figure.Voici un exemple trivial qui provoque l'avertissement:
Pour éviter l'avertissement, je dois tirer l'appel à l'
subplots()
extérieur de la boucle. Pour continuer à voir les rectangles, je dois passerclf()
àcla()
. Cela efface l'axe sans supprimer l'axe lui-même.Si vous générez des graphiques par lots, vous devrez peut-être utiliser à la fois
cla()
etclose()
. J'ai rencontré un problème où un lot pouvait avoir plus de 20 parcelles sans se plaindre, mais il se plaindrait après 20 lots. J'ai corrigé cela en utilisantcla()
après chaque parcelle etclose()
après chaque lot.J'ai mesuré les performances pour voir s'il valait la peine de réutiliser la figure dans un lot, et ce petit programme d'exemple a ralenti de 41s à 49s (20% plus lent) lorsque je viens d'appeler
close()
après chaque tracé.la source
Si vous avez l'intention de garder sciemment de nombreux tracés en mémoire, mais que vous ne voulez pas en être averti, vous pouvez mettre à jour vos options avant de générer des chiffres.
Cela empêchera l'émission de l'avertissement sans rien changer à la façon dont la mémoire est gérée.
la source
L'extrait de code suivant a résolu le problème pour moi:
Quand il
_wrapped_figure
est hors de portée, le runtime appelle notre__del__()
méthode avecplt.close()
inside. Cela se produit même si l'exception se déclenche après le_wrapped_figure
constructeur.la source
Ceci est également utile si vous souhaitez uniquement supprimer temporairement l'avertissement:
la source