une fuite de mémoire Python en utilisant PyQt et matplotlib
-
12-09-2019 - |
Question
J'ai créé un petit utilitaire PyQt en Python qui crée des graphiques PNG en utilisant matplotlib lorsqu'un utilisateur clique sur un bouton. Tout fonctionne bien pendant les premiers clics, mais chaque fois qu'une image est créée, l'empreinte mémoire de l'application se développe environ 120 Mo, éventuellement écraser Python tout à fait.
Comment puis-je récupérer cette mémoire après un graphique est créé? J'ai inclus une version simplifiée de mon code ici:
import datetime as dt
from datetime import datetime
import os
import gc
# For Graphing
import matplotlib
from pylab import figure, show, savefig
from matplotlib import figure as matfigure
from matplotlib.dates import MonthLocator, WeekdayLocator, DateFormatter, DayLocator
from matplotlib.ticker import MultipleLocator
import matplotlib.pyplot as plot
import matplotlib.ticker as ticker
# For GUI
import sys
from PyQt4 import QtGui, QtCore
class HyperGraph(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('Title')
self.create_widgets()
def create_widgets(self):
grid = QtGui.QGridLayout()
self.generate_button = QtGui.QPushButton("Generate Graph", self)
grid.addWidget(self.generate_button, 1, 1)
QtCore.QObject.connect(self.generate_button, QtCore.SIGNAL("clicked()"), self.generate_graph)
def generate_graph(self):
try:
fig = figure()
ax = fig.add_axes([1,1,1,1])
# set title
ax.set_title('Title')
# configure x axis
plot.xlim(dt.date.today() - dt.timedelta(days=180), dt.date.today())
ax.set_xlabel('Date')
fig.set_figwidth(100)
# configure y axis
plot.ylim(0, 200)
ax.set_ylabel('Price')
fig.set_figheight(30)
# export the graph to a png file
plot.savefig('graph.png')
except:
print 'Error'
plot.close(fig)
gc.collect()
app = QtGui.QApplication(sys.argv)
hyper_graph = HyperGraph()
hyper_graph.show()
sys.exit(app.exec_())
La commande plot.savefig ( 'de graph.png') semble être ce qui engloutissant la mémoire.
J'apprécierais toute aide!
La solution
Il semble que certains backends fuient la mémoire. Essayez de configurer votre backend explicitement, par exemple.
import matplotlib
matplotlib.use('Agg') # before import pylab
import pylab
Autres conseils
L'interface pyplot est conçu pour une utilisation interactive facile, mais pour l'intégration dans une application l'API orientée objet est mieux. Par exemple, pyplot garde la trace de tous les chiffres que vous avez créés. Votre plot.close(figure)
devrait se débarrasser d'eux, mais peut-être qu'il ne soit pas exécuté -. Essayez de le mettre à l'intérieur finally
ou réutiliser le même objet figure
Voir cet exemple d'intégration matplotlib dans une application utilisant le PyQt4 object- API orientée. Il est plus de travail, mais puisque tout est explicite, vous ne devriez pas obtenir les fuites de mémoire de l'automatisation derrière les scènes qui pyplot fait.