编辑:如果我明确地将matplotlib的后端从'Qt4Agg'更改为'Agg',那么我就可以运行我的代码而没有错误。我认为这是后端的一个错误?
我正在编写一些代码来自动处理大量数据。代码首先解析我的数据文件并存储所有相关的位。然后,我有不同的功能来生成我需要的每个图形(总共大约有25个)。但是,我一直遇到某种内存错误,我认为这是因为Matplotlib / PyPlot没有正确释放内存。
每个绘图函数都以pyplot.close(fig)命令结束,因为我只是想保存图形而不是立即查看它们不包含pyplot.show()。
如果我在翻译中单独运行绘图功能,那么我不会遇到任何问题。但是,如果我创建一个单独调用每个绘图函数的函数,那么我会遇到“MemoryError:无法为路径分配内存”。
有没有人遇到过这样的问题?它似乎与Matplotlib runs out of memory when plotting in a loop有关,但pyplot.close()并不能解决我的问题。
这是我的代码中典型的绘图函数:
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)
如果我现在在终端中运行
MyClass.TypicalPlot(save=True, show = False)
然后我没有得到任何错误。我的所有绘图功能都是如此。
如果我创建了一个新功能:
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:无法为路径分配内存”。
答案 0 :(得分:1)
我认为这样做的原因是因为它经历了所有不同的图形,然后耗尽内存可能是因为它没有正确地释放它。
为什么不尝试创建大约3个左右的程序,每个程序执行一些图形而不是一个程序执行所有图形:
计划1:图1-8
计划2:图表9-16
计划3:图17-25
希望这有助于@FakeDIY:)
答案 1 :(得分:1)
我遇到过一次非常类似的问题。我假设matplotlib在内部保留每个图的参考。给出以下代码,创建三个单独的数字:
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
这是违反直觉的,因为我们多次重新定义了f
和ax
。
对于每个块,我们创建了一个新图形,可以通过plt
引用。创建另一个数字会更改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
,程序将直接运行