使用具有性能考虑因素的matplotlib在动画中泄漏内存

时间:2017-11-30 08:38:07

标签: python animation matplotlib

最近我正在使用matplotlib的python做动画。在开始时,我按照在网络中搜索的示例,其具有以下结构:

=========================================================================
import matplotlib.pyplot as plot
import matplotlib.animation as anim

def animate(i):
    ax.clear()
    # Re-plot the figure with updated animation data

if __name__ == "__main__":
    fig, ax = plot.subplots(fsigsize=(8,4))
    an = anim.FuncAnimation(fig, animate, interval=1)
    plot.show()
=========================================================================

此代码似乎没问题。没有内存泄漏。但问题是它运行得太慢了。因为当使用更新的动画数据重新生成绘图时,绘图的所有设置(例如,set_xlim(),set_ylim(),绘图轴,......等)必须一次又一次地完成。因此,我试图以这种方式改善表现:

========================================================================
import matplotlib.pyplot as plot
import matplotlib.animation as anim

def init():
    ax.set_title("....")
    ax.set_xlim(-1, 1)
    ax.set_ylim(-10,10)
    # plot axes, and all the patterns which are fixed in the animation

def animate(i):
    # x[] and y[] are large arrays with updated animation data
    if ('la' in globals()): la.remove()
    la, = ax.plot(x, y)

if __name__ == "__main__":
    fig, ax = plot.subplots(figsize=(8,4))
    an = anim.FuncAnimation(fig, animate, init_func=init, interval=1)
    plot.show()
========================================================================

这样只有主曲线" la"被重新绘制。其他固定部分仅在init()子例程中完成一次。现在动画运行得更快。但是出现严重的内存泄漏。跑步"顶部"在动画中,我看到被占用的内存不断增长。经过测试,我确信这个语句是内存泄漏的来源:

la, = ax.plot(x, y)

一些讨论表明内存泄漏是由于情节" ax"没有关闭。但是如果我每次关闭情节来更新数字,那么表现就会太慢了。

有没有更好的方法来解决这个问题?

我的环境:Python 3.4,matplotlib-1.4.2,Debian GNU / Linux 8.8。我还在Python 3.6,Cygwin和MacOS X下的matplotlib-2.1.0中进行了测试。情况是一样的。

非常感谢你的帮助。

T.H.Hsieh

1 个答案:

答案 0 :(得分:-1)

抱歉,我只是想出答案。更新动画中的绘图的正确方法是保持性能并且没有内存泄漏,应该“设置新数据”,而不是“删除和重绘曲线”或“重新生成绘图”。因此我的代码应该改为:

=====================================================================
import matplotlib.pyplot as plot
import matplotlib.animation as anim

def init():
    global ax, la
    ax.set_title("....")
    ax.set_xlim(-1, 1)
    ax.set_ylim(-10,10)
    # get the initial data x[], y[] to plot the initial curve
    la, = ax.plot(x, y, color="red", lw=1)

def animate(i):
    global fig, la
    # update the data x[], y[], set the updated data, and redraw.
    la.set_xdata(x)
    la.set_ydata(y)
    fig.canvas.draw()

if __name__ == "__main__":
    fig, ax = plot.subplots(fsigsize=(8,4))
    an = anim.FuncAnimation(fig, animate, interval=1)
    plot.show()
=====================================================================    

无论如何,感谢那些给我评论的人,这表明我找到了答案。

最诚挚的问候,

T.H.Hsieh