Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python leaking memory while using PyQt and matplotlib

I've created a small PyQt based utility in Python that creates PNG graphs using matplotlib when a user clicks a button. Everything works well during the first few clicks, however each time an image is created, the application's memory footprint grows about 120 MB, eventually crashing Python altogether.

How can I recover this memory after a graph is created? I've included a simplified version of my code here:

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_())

The plot.savefig('graph.png') command seems to be what's gobbling up the memory.

I'd greatly appreciate any help!

like image 342
Eric the Red Avatar asked Aug 08 '09 15:08

Eric the Red


2 Answers

It seems that some backends are leaking memory. Try setting your backend explicitly, e.g.

import matplotlib
matplotlib.use('Agg') # before import pylab
import pylab
like image 60
wierob Avatar answered Nov 10 '22 08:11

wierob


The pyplot interface is meant for easy interactive use, but for embedding in an application the object-oriented API is better. For example, pyplot keeps track of all figures you have created. Your plot.close(figure) should get rid of them, but maybe it doesn't get executed -- try putting it inside finally or reusing the same figure object.

See this example of embedding matplotlib in a PyQt4 application using the object-oriented API. It's more work, but since everything is explicit, you shouldn't get memory leaks from the behind-the-scenes automation that pyplot does.

like image 34
Jouni K. Seppänen Avatar answered Nov 10 '22 08:11

Jouni K. Seppänen