Python 在循环中打印时,Matplotlib内存不足

Python 在循环中打印时,Matplotlib内存不足,python,numpy,matplotlib,Python,Numpy,Matplotlib,我有一个相当简单的绘图例程,如下所示: from __future__ import division import datetime import matplotlib matplotlib.use('Agg') from matplotlib.pyplot import figure, plot, show, legend, close, savefig, rcParams import numpy from globalconstants import * def plotCol

我有一个相当简单的绘图例程,如下所示:

from __future__ import division
import datetime
import matplotlib
matplotlib.use('Agg')
from matplotlib.pyplot import figure, plot, show, legend, close, savefig, rcParams
import numpy
from globalconstants import *

    def plotColumns(columnNumbers, t, out, showFig=False, filenamePrefix=None, saveFig=True, saveThumb=True):
        lineProps = ['b', 'r', 'g', 'c', 'm', 'y', 'k', 'b--', 'r--', 'g--', 'c--', 'm--', 'y--', 'k--', 'g--', 'b.-', 'r.-', 'g.-', 'c.-', 'm.-', 'y.-', 'k.-']

        rcParams['figure.figsize'] = (13,11)
        for i in columnNumbers:
            plot(t, out[:,i], lineProps[i])

        legendStrings = list(numpy.zeros(NUMCOMPONENTS)) 
        legendStrings[GLUCOSE] = 'GLUCOSE'
        legendStrings[CELLULOSE] = 'CELLULOSE'
        legendStrings[STARCH] = 'STARCH'
        legendStrings[ACETATE] = 'ACETATE'
        legendStrings[BUTYRATE] = 'BUTYRATE'
        legendStrings[SUCCINATE] = 'SUCCINATE'
        legendStrings[HYDROGEN] = 'HYDROGEN'
        legendStrings[PROPIONATE] = 'PROPIONATE'
        legendStrings[METHANE] = "METHANE"

        legendStrings[RUMINOCOCCUS] = 'RUMINOCOCCUS'
        legendStrings[METHANOBACTERIUM] = "METHANOBACTERIUM"
        legendStrings[BACTEROIDES] = 'BACTEROIDES'
        legendStrings[SELENOMONAS] = 'SELENOMONAS'
        legendStrings[CLOSTRIDIUM] = 'CLOSTRIDIUM'

        legendStrings = [legendStrings[i] for i in columnNumbers]
        legend(legendStrings, loc='best')

        dt = datetime.datetime.now()
        dtAsString = dt.strftime('%d-%m-%Y_%H-%M-%S')

        if filenamePrefix is None:
            filenamePrefix = ''

        if filenamePrefix != '' and filenamePrefix[-1] != '_':
            filenamePrefix += '_'

        if saveFig: 
            savefig(filenamePrefix+dtAsString+'.eps')

        if saveThumb:
            savefig(filenamePrefix+dtAsString+'.png', dpi=300)


        if showFig: f.show()

        close('all')
当我在一次迭代中绘制此图时,效果很好。然而,当我把它放入一个循环中时,matplotlib发出嘶嘶的声音

Traceback (most recent call last):
  File "c4hm_param_variation_h2_conc.py", line 148, in <module>
    plotColumns(columnNumbers, timeVector, out, showFig=False, filenamePrefix='c
4hm_param_variation_h2_conc_'+str(hydrogen_conc), saveFig=False, saveThumb=True)

  File "D:\phdproject\alexander paper\python\v3\plotcolumns.py", line 48, in plo
tColumns
    savefig(filenamePrefix+dtAsString+'.png', dpi=300)
  File "C:\Python25\lib\site-packages\matplotlib\pyplot.py", line 356, in savefi
g
    return fig.savefig(*args, **kwargs)
  File "C:\Python25\lib\site-packages\matplotlib\figure.py", line 1032, in savef
ig
    self.canvas.print_figure(*args, **kwargs)
  File "C:\Python25\lib\site-packages\matplotlib\backend_bases.py", line 1476, i
n print_figure
    **kwargs)
  File "C:\Python25\lib\site-packages\matplotlib\backends\backend_agg.py", line
358, in print_png
    FigureCanvasAgg.draw(self)
  File "C:\Python25\lib\site-packages\matplotlib\backends\backend_agg.py", line
314, in draw
    self.figure.draw(self.renderer)
  File "C:\Python25\lib\site-packages\matplotlib\artist.py", line 46, in draw_wr
apper
    draw(artist, renderer, *kl)
  File "C:\Python25\lib\site-packages\matplotlib\figure.py", line 773, in draw
    for a in self.axes: a.draw(renderer)
  File "C:\Python25\lib\site-packages\matplotlib\artist.py", line 46, in draw_wr
apper
    draw(artist, renderer, *kl)
  File "C:\Python25\lib\site-packages\matplotlib\axes.py", line 1735, in draw
    a.draw(renderer)
  File "C:\Python25\lib\site-packages\matplotlib\artist.py", line 46, in draw_wr
apper
    draw(artist, renderer, *kl)
  File "C:\Python25\lib\site-packages\matplotlib\legend.py", line 374, in draw
    bbox = self._legend_box.get_window_extent(renderer)
  File "C:\Python25\lib\site-packages\matplotlib\offsetbox.py", line 209, in get
_window_extent
    px, py = self.get_offset(w, h, xd, yd)
  File "C:\Python25\lib\site-packages\matplotlib\offsetbox.py", line 162, in get
_offset
    return self._offset(width, height, xdescent, ydescent)
  File "C:\Python25\lib\site-packages\matplotlib\legend.py", line 360, in findof
fset
    return _findoffset(width, height, xdescent, ydescent, renderer)
  File "C:\Python25\lib\site-packages\matplotlib\legend.py", line 325, in _findo
ffset_best
    ox, oy = self._find_best_position(width, height, renderer)
  File "C:\Python25\lib\site-packages\matplotlib\legend.py", line 817, in _find_
best_position
    verts, bboxes, lines = self._auto_legend_data()
  File "C:\Python25\lib\site-packages\matplotlib\legend.py", line 669, in _auto_
legend_data
    tpath = trans.transform_path(path)
  File "C:\Python25\lib\site-packages\matplotlib\transforms.py", line 1911, in t
ransform_path
    self._a.transform_path(path))
  File "C:\Python25\lib\site-packages\matplotlib\transforms.py", line 1122, in t
ransform_path
    return Path(self.transform(path.vertices), path.codes,
  File "C:\Python25\lib\site-packages\matplotlib\transforms.py", line 1402, in t
ransform
    return affine_transform(points, mtx)
MemoryError: Could not allocate memory for path
回溯(最近一次呼叫最后一次):
文件“c4hm_参数_变体_h2_conc.py”,第148行,在
plotColumns(ColumnNumber、timeVector、out、showFig=False、filenamePrefix='c
4hm参数变化h2浓度+str(氢气浓度),saveFig=False,saveThumb=True)
文件“D:\phdproject\alexander paper\python\v3\plotcolumns.py”,plo中的第48行
T柱
savefig(filenamePrefix+dtAsString+'.png',dpi=300)
savefi中第356行的文件“C:\Python25\lib\site packages\matplotlib\pyplot.py”
G
返回图savefig(*args,**kwargs)
savef中的文件“C:\Python25\lib\site packages\matplotlib\figure.py”,第1032行
免疫球蛋白
self.canvas.print_图(*args,**kwargs)
文件“C:\Python25\lib\site packages\matplotlib\backend\u base.py”,第1476行,i
n打印图形
**kwargs)
文件“C:\Python25\lib\site packages\matplotlib\backends\backend\u agg.py”,第行
358,印在png
图CAVASAGG.draw(自绘制)
文件“C:\Python25\lib\site packages\matplotlib\backends\backend\u agg.py”,第行
314,平局
self.figure.draw(self.renderer)
文件“C:\Python25\lib\site packages\matplotlib\artist.py”,第46行,在draw\u wr中
阿佩尔
绘制(艺术家、渲染器,*kl)
文件“C:\Python25\lib\site packages\matplotlib\figure.py”,第773行,在绘图中
对于在self.axes中的渲染器:a.draw(渲染器)
文件“C:\Python25\lib\site packages\matplotlib\artist.py”,第46行,在draw\u wr中
阿佩尔
绘制(艺术家、渲染器,*kl)
文件“C:\Python25\lib\site packages\matplotlib\axes.py”,第1735行,在绘图中
a、 绘制(渲染器)
文件“C:\Python25\lib\site packages\matplotlib\artist.py”,第46行,在draw\u wr中
阿佩尔
绘制(艺术家、渲染器,*kl)
文件“C:\Python25\lib\site packages\matplotlib\legend.py”,第374行,在绘图中
bbox=self.\u图例\u框。获取\u窗口\u范围(渲染器)
get中第209行的文件“C:\Python25\lib\site packages\matplotlib\offsetbox.py”
_窗口范围
px,py=自身获取偏移量(w,h,xd,yd)
get中第162行的文件“C:\Python25\lib\site packages\matplotlib\offsetbox.py”
_抵消
返回自偏移(宽度、高度、xdescent、xdescent)
文件“C:\Python25\lib\site packages\matplotlib\legend.py”,第360行,在findof中
fset
return\u findoffset(宽度、高度、xdescent、xdescent、渲染器)
文件“C:\Python25\lib\site packages\matplotlib\legend.py”,第325行,在findo中
最佳补偿
ox,oy=自身。查找最佳位置(宽度、高度、渲染器)
文件“C:\Python25\lib\site packages\matplotlib\legend.py”,第817行,在\ u find中_
最佳位置
顶点、长方体、直线=自身。\自动\图例\数据()
文件“C:\Python25\lib\site packages\matplotlib\legend.py”,第669行,在_auto中_
图例数据
tpath=传输变换路径(路径)
文件“C:\Python25\lib\site packages\matplotlib\transforms.py”,第1911行,t
变换路径
自我转换路径(路径))
文件“C:\Python25\lib\site packages\matplotlib\transforms.py”,第1122行,在t中
变换路径
返回路径(自变换(路径顶点)、路径代码、,
文件“C:\Python25\lib\site packages\matplotlib\transforms.py”,第1402行,在t中
转变
返回仿射变换(点,mtx)
MemoryError:无法为路径分配内存
这发生在迭代2上(从1开始计算),如果有区别的话。代码运行在Windows XP 32位上,使用python 2.5和matplotlib 0.99.1、numpy 1.3.0和scipy 0.7.1


编辑:代码现在已经更新,以反映在调用
legend()时实际发生崩溃的事实
。对调用进行注释可以解决问题,尽管很明显,我仍然希望能够在我的图形上添加图例…

每个循环都应该生成一个新的图形吗?我看不到您在循环之间关闭它或创建一个新的图形实例

在循环结束时保存当前图形后,此调用将清除当前图形:

pyplot.clf()

不过,我会进行重构,使您的代码更加面向对象,并在每个循环上创建一个新的figure实例:

from matplotlib import pyplot

while True:
  fig = pyplot.figure()
  ax = fig.add_subplot(111)
  ax.plot(x,y)
  ax.legend(legendStrings, loc = 'best')
  fig.savefig('himom.png')
  # etc....

我也遇到了这个错误。似乎是什么解决了它

while True:
    fig = pyplot.figure()
    ax = fig.add_subplot(111)
    ax.plot(x,y)
    ax.legend(legendStrings, loc = 'best')
    fig.savefig('himom.png')
    #new bit here
    pylab.close(fig) #where f is the figure

现在在内存波动的情况下稳定地运行我的循环,但没有持续增加

忍者的回答对我来说也很有效-
pyplot.close()
使我的循环能够工作

在pyplot教程中:

可以使用和清除当前地物 如果你觉得这种庄重、烦人,不要 绝望,这只是一个围绕对象的薄薄的有状态包装器 面向API,您可以改用它(请参阅)

如果你正在制作一个长序列的图形,你需要意识到 还有一件事:图形所需的内存不是完全可用的 释放,直到图形使用显式关闭。删除 对图形的所有引用,和/或使用窗口管理器终止 图形出现在屏幕上的窗口不够, 因为pyplot在调用之前一直保持内部引用


呸!我忘记了
clf()
调用…添加该调用修复了它。从@geographica的回答来看,
clf()
似乎清除了图形,但没有释放对它的所有引用,不像
close(图)
。清除时,它不会保留太多内存,但如果有很多内存,它会累积起来……因此,如果我有一个大约30k值的实时绘图,并且我有其他需要绘图的圆弧、椭圆、圆,pyplot.clf()具体做什么?对于动画,我也使用了pyplot.pause(time\u duration)。如何保留之前绘制的值,然后在获取数据时一次又一次地绘制这些值?对我来说,它还帮助我不时手动运行Python的垃圾收集以消除内存不足错误。为此,我在代码顶部添加了
import gc
,然后在
close()之后添加了
gc.collect()
(或偶尔,视情况而定