Python在使用PyQt和matplotlib时会出现内存泄漏问题。

6
我用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')命令在占用内存。

如果能帮到忙,我将不胜感激!


如果您想在GUI中使用,请勿使用pyplot创建图形,而是使用Figure创建图形实例。 - bactone
2个回答

7

看起来一些后端正在泄漏内存。尝试明确设置您的后端,例如:

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

谢谢!这个效果非常好。我需要仔细研究您的回答的更多细节。 - Eric the Red

7

Pyplot接口旨在实现易于交互的使用,但对于嵌入应用程序,面向对象的API更好。例如,pyplot跟踪您创建的所有图形。您的plot.close(figure)应该将它们清除,但可能不会执行--尝试将其放在finally中或重用同一图形对象。

请参见此示例,使用面向对象的API在PyQt4应用程序中嵌入matplotlib。这需要更多的工作,但由于一切都是明确的,所以您不应该从pyplot进行的幕后自动化中获得内存泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接