xPython savefig内存泄漏尚未解决以前提出的解决方案

时间:2013-11-18 22:04:34

标签: python memory-leaks matplotlib

编辑:已解决

但我不确定如何...我尽可能多地移动到pylab而不是pyplot,实现了[here] [1]中描述的多处理方法,并且在那一点上它运行正常。然后,为了查明问题,我逐步颠倒了我的代码。但即使没有多处理,它也能继续工作,即使是使用pyplot等。只有当我取下fig.clf()现在它不起作用,这是大多数人似乎经历的但最初不是我的问题。好吧也许是,也许clf()声明不在正确的地方或什么的。谢谢!

编辑:问题仍未解决

这非常令人惊讶。我现在将我的savefig()函数移动到外部模块中,我在执行脚本时导入该模块。这是功能:

def savethefig(fig,outpath,luname):
    plt.savefig(outpath+luname+'testredtarget.png',dpi=500)

所以现在我做了类似的事情:

from myfile import savethefig
fig = plt.figure()
ax1 = fig.add_subplot(311)
pftmap=zeros(shape=(1800,3600))*nan
    for i in range(len(pftspatialnames)):
       pftmap[indlat,indlon]=data[i,:]
       fig = pylab.gcf()
       a1=ax1.imshow(pftmap, interpolation='nearest',origin='upper', aspect='auto')
       savethefig(fig,outpath,luname)

我一步一步地逐步完成所有事情,当在外部函数中单击savefig()函数时,RAM肯定会上升。增加约500MB。然后当回到主脚本时,该内存不会被释放。 是不是外部功能应该清除一切?我错过了什么......

原始邮件:

我正在使用python EDP 7.3-2(32位)(python 2.7.3)。

我有一个程序可以进行一些计算,然后使用matplotlib将一些结果映射出来并保存图像。

这是一个非常大量的数据,如果我尝试映射并保存太多图像,我会达到内存限制。我不应该使用相同的数字,并且不要创建新的变量。我已经挣扎了一段时间,尝试了所有的数字清除/删除等解决方案,改变matplotlib使用的后端,但没有什么,每次代码点击savefig函数,它增加了大量的内存,并没有采取它晚了。

我远远不是内存中的专家(或顺便说一下python),但这是我使用模块对象运行的一次诊断尝试:

from numpy import *
import matplotlib
matplotlib.use('Agg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib import pyplot as plt

outpath = '/Users/yannick/Documents/outputs/'
pftspatialnames = ['forest','shrubs','grass']

Computations (not shown)

fig = plt.figure()
for i in range(len(pftspatialnames)):
   pftmap=zeros(shape=(1800,3600))*nan
   pftmap[indlat,indlon]=data[i,:]
   fig = pylab.gcf()
   ax1 = plt.subplot2grid((3,1),(0,0))
   a1=ax1.imshow(pftmap, interpolation='nearest',origin='upper', aspect='auto')
   del(pftmap)
   gc.collect()

   print 'MEMORY LEAK DETECTOR before figsave'
   objgraph.show_growth()

   plt.savefig(outpath+pftspatialnames[i]+'testredtarget.png', dpi=500)

   print 'MEMORY LEAK DETECTOR after figsave'
   objgraph.show_growth()

相当大的地图(其中有3个,3个子图,只是在这里显示了一个),但它处理得非常好。大约4个数字可以使记忆饱和。有些东西可能是多余的(例如删除pftmap),但我正在尝试清理一些内存。

以下是打印输出:

MEMORY LEAK DETECTOR before figsave
dict                6640     +2931
weakref             3218     +1678
instance            1440     +1118
tuple               3501      +939
function           12486      +915
Bbox                 229      +229
instancemethod       684      +171
Line2D               147      +147
TransformedBbox      115      +115
Path                 127      +114
MEMORY LEAK DETECTOR after figsave
dict                7188      +548
Path                 422      +295
weakref             3494      +276
instance            1679      +239
tuple               3703      +202
function           12670      +184
TransformedPath       87       +87
instancemethod       741       +57
Line2D               201       +54
FontProperties       147       +36

所以在调用savefig之前有很多新对象(这是正常的,我之前在代码中做了很多东西)。但是,然后通过调用savefig我们添加550 dict等。这可能是我的问题的根源吗?请注意,这是在我第一次调用savefig时发生的。任何后续调用都会执行以下操作:

MEMORY LEAK DETECTOR before figsave
MEMORY LEAK DETECTOR after figsave
tuple        3721        +6
dict         7206        +6
function    12679        +3
list         2001        +3
weakref      3503        +3
instance     1688        +3
Bbox          260        +3

但是记忆力仍在不断增长,很快就达到了内存限制。

非常感谢!

3 个答案:

答案 0 :(得分:0)

用Google搜索的轶事证据似乎表明执行了“matplotlib.pyplot.close”。在savefig之后将回收/释放与该图相关联的内存。有关所有调用选项,请参阅pyplot文档。

答案 1 :(得分:0)

我忘了哪个堆栈溢出线程/网站我找到了这个解决方案,但直接使用图(而不是触及pyplot状态机)通常可以解决问题。所以:

fig = figure.Figure()
canvas = FigureCanvas(fig)
...
canvas.print_figure(outpath+pftspatialnames[i]+'testredtarget.png', dpi=500)

答案 2 :(得分:0)

编辑:已解决

但我不确定如何...我尽可能多地移动到pylab而不是pyplot,实现了[here] [1]中描述的多处理方法,并且在那一点上它运行正常。然后,为了查明问题,我逐步颠倒了我的代码。但即使没有多处理,它也能继续工作,即使是使用pyplot等。只有当我取下fig.clf()现在它不起作用,这是大多数人似乎经历的但最初不是我的问题。好吧也许是,也许clf()声明不在正确的地方或什么的。谢谢