Matplotlib和Pyplot.close()不释放内存? – 后端相关的Qt4Agg

编辑:如果我明白更改后台matplotlib从'Qt4Agg'只是'聚',那么我能够运行我的代码没有错误。 我认为这是后端的错误?

我正在编写一些自动处理大量数据的代码。 代码首先parsing我的数据文件并存储所有相关的位。 然后我有不同的function来生成我需要的每个图表(大约有25个)。 但是,我不断遇到某种内存错误,我认为这是因为Matplotlib / PyPlot没有正确释放内存。

每个绘图函数都以pyplot.close(fig)命令结束,因为我只是想保存graphics而不是立即查看它们,所以包含pyplot.show()。

如果我在解释器中分别运行绘图函数,那么我不会遇到任何问题。 但是,如果我做一个单独的函数,依次调用每个绘图函数,那么我会遇到“MemoryError:无法为path分配内存”。

有没有人遇到这样的问题? 这似乎与Matplotlib在循环绘制时耗尽内存有关,但pyplot.close()不能解决我的问题。

这是我的代码中典型的绘图function的样子:

def TypicalPlot(self, title=None, comment=False, save=False, show=True): if title is None: title = self.dat.title fig = plt.figure() host = SubplotHost(fig, 111) fig.add_subplot(host) par = host.twinx() host.set_xlabel("Time (hrs)") host.set_ylabel("Power (W)") par.set_ylabel("Temperature (C)") p1, = host.plot(self.dat.timebase1, self.dat.pwr, 'b,', label="Power", markevery= self.skip) p2, = par.plot(self.dat.timebase2, self.dat.Temp1, 'r,', label="Temp 1", markevery= self.skip) p3, = par.plot(self.dat.timebase2, self.dat.Temp2, 'g,', label="Temp 2", markevery= self.skip) p4, = par.plot(self.dat.timebase2, self.dat.Temp3, 'm,', label="Temp 3", markevery= self.skip) host.axis["left"].label.set_color(p1.get_color()) # par.axis["right"].label.set_color(p2.get_color()) #host.legend(loc='lower left') plt.title(title+" Temperature") leg=host.legend(loc='lower left',fancybox=True) #leg.get_frame().set_alpha(0.5) frame = leg.get_frame() frame.set_facecolor('0.80') ### make the legend text smaller for t in leg.get_texts(): t.set_fontsize('small') ### set the legend text color to the same color as the plots for added ### readability leg.get_texts()[0].set_color(p1.get_color()) leg.get_texts()[1].set_color(p2.get_color()) leg.get_texts()[2].set_color(p3.get_color()) leg.get_texts()[3].set_color(p4.get_color()) if show is True and save is True: plt.show() plt.savefig('temp.png') elif show is True and save is False: plt.show() elif show is False and save is True: plt.savefig('temp.png') plt.clf() plt.close(fig) 

如果我现在在terminal运行

 MyClass.TypicalPlot(save=True, show = False) 

然后我没有得到任何错误。 我所有的情节function也是如此。

如果我做一个这样做的新function:

 def saveAllPlots(self, comments = False): if self.comment is None: comment = False else: comment = True self.TypicalPlot(save=True, show=False, comment=comment) self.AnotherPlot(save=True, show=False) self.AnotherPlot2(save=True, show=False) self.AnotherPlot3(save=True, show=False) ...etc, etc, etc 

然后它通过大约一半的图表,然后我得到“MemoryError:不能分配内存的path”。

我认为这样做的原因是因为当它通过所有不同的图表时,内存耗尽可能是因为它没有正确释放它。

你为什么不尝试创build大约3个左右的程序,每个程序做几个图,而不是一个程序做所有的图:

计划1:图表1-8

计划2:图表9-16

计划3:图17-25

希望这有助于@FakeDIY:)

我遇到了一个非常类似的问题。 我假设matplotlib保持内部每个图的引用。 给出以下代码,创build三个单独的数字:

 import matplotlib.pyplot as plt import numpy as np # block 1 f, ax = plt.subplots(1) plt.plot(np.arange(10), np.random.random(10)) plt.title("first") print 'first', sys.getrefcount(f), sys.getrefcount(ax) # bock 2 f, ax = plt.subplots(1) plt.plot(np.arange(10), np.random.random(10)+1) plt.title("second") print 'second', sys.getrefcount(f), sys.getrefcount(ax) # block 3 f, ax = plt.subplots(1) plt.plot(np.arange(10), np.random.random(10)+2) plt.title("third") print 'third', sys.getrefcount(f), sys.getrefcount(ax) plt.show() print 'after show', sys.getrefcount(f), sys.getrefcount(ax) 

输出:

 first 69 26 second 69 26 third 69 26 after show 147 39 

这是违反直觉的,因为我们重新定义了fax几次。 随着每一个块,我们创build了一个新的graphics,可以通过plt引用。 创build另一个graphics会更改plt可访问的最顶层引用。 但是必须有一些内部的参考,它允许plt.show()显示所有的数字。 这些引用似乎是持久的,因此这些数字不会被gc收集。

我解决的解决方法是改变情节的数据。 事后看来,这是一个更好的方法:

 plt.ion() f, ax = plt.subplots(1) line = ax.plot(np.arange(10), np.random.random(10))[0] plt.title('first') plt.show() for i, s in [(2, 'second'), (3, 'third')]: x = np.arange(10) y = np.random.random(10)+i line.set_data(x, y) ax.set_xlim(np.min(x), np.max(x)) ax.set_ylim(np.min(y), np.max(y)) plt.title(s) plt.draw() raw_input(s) 

唯一的缺点是你必须保持打开图的窗口。 没有raw_input ,程序就会运行