Python在使用PyQt和matplotlib时泄漏内存

时间:2009-08-08 15:49:15

标签: python memory-leaks pyqt matplotlib

我在Python中创建了一个基于PyQt的小实用程序,当用户单击按钮时,使用matplotlib创建PNG图形。在前几次点击期间,一切运行良好,但每次创建图像时,应用程序的内存占用量增加约120 MB,最终会使Python崩溃。

创建图表后如何恢复此内存?我在这里包含了我的代码的简化版本:

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

plot.savefig('graph.png')命令似乎正在吞噬内存。

我非常感谢任何帮助!

2 个答案:

答案 0 :(得分:7)

似乎有些后端正在泄漏内存。尝试明确设置后端,例如

import matplotlib
matplotlib.use('Agg') # before import pylab
import pylab

答案 1 :(得分:6)

pyplot接口是为了便于交互使用,但是为了嵌入到应用程序中,面向对象的API更好。例如,pyplot会跟踪您创建的所有数字。你的plot.close(figure) 应该摆脱它们,但也许它不会被执行 - 尝试将它放在finally内或重用相同的图形对象。

使用面向对象的API,在PyQt4应用程序中查看嵌入matplotlib的this example。这是更多的工作,但由于一切都是明确的,你不应该从pyplot的幕后自动化中获得内存泄漏。