Matplotlib动画几帧后冻结或根本无法工作

6 投票
8 回答
14669 浏览
提问于 2025-04-16 02:32

我花了好几个小时想让这个简单的脚本运行起来,但无论我怎么做都没有效果。这段代码是从Matplotlib网站上最基本的动画绘图示例代码稍微修改过的,应该只显示几帧噪声(顺便说一下,我用他们网站上未修改的代码也遇到同样的问题)。

在我电脑上使用TkAgg后端时,我能看到大约20帧(总共60帧),然后绘图窗口就卡住了。而使用Qt4Agg时,我只看到一个黑色的冻结窗口,根本没有任何帧被绘制出来。我尝试了多种不同版本的NumPy、PyQt、Python和Matplotlib组合,但结果总是一样。

请告诉我这对你是否有效,或者有没有什么看起来不对的地方。我很确定以前这个是能正常工作的,所以我在想可能是Windows的问题,或者和ion()有关。

顺便说一下,我使用的是Windows 7(32位),测试过Python 2.6/2.7,MPL 1.0.0/0.9.9.8,PyQt 4.6/4.7,Numpy 1.4/1.5b。

import matplotlib
matplotlib.use('TkAgg') # Qt4Agg gives an empty, black window
from pylab import *
import time

ion()
hold(False)

# create initial plot
z = zeros(10)
line, = plot(z)
ylim(-3, 3)

for i in range(60):
    print 'frame:', i

    d = randn(10)
    line.set_ydata(d)

    draw()
    time.sleep(10e-3)

这个更简单的版本在前几帧后也会卡住:

from pylab import *

ion()
hold(False)

for i in range(40):
    plot(randn(10))
    draw()

show()

谢谢!

编辑:这些人似乎也遇到了和我相同或类似的问题:

  • mail-archive.com/matplotlib-users@lists.sourceforge.net/msg10844.html
  • stackoverflow.com/questions/2604119/matplotlib-pyplot-pylab-not-updating-figure-while-isinteractive-using-ipython
  • mail-archive.com/matplotlib-users@lists.sourceforge.net/msg01283.html

看起来他们也没有找到解决办法 :(

8 个回答

1

当你说动画在前几帧后卡住,是指2、3帧,还是说40、60帧,因为这些是你循环的上限?

如果你想让动画一直继续下去,你需要像下面这样做:

while True:
    d = randn(10)
    line.set_ydata(d)
    draw()
    time.sleep(10e-3)

不过你可能需要强制退出你的程序。

2

经过很多小时的挣扎,我终于找到了答案:要用matplotlib做这些简单的动画,你只能使用GTKAgg后端。在scipy的食谱中提到过这一点,但我觉得应该更明确地强调一下。当我使用这个后端时,我可以顺利地运行你的动画,直到结束,没有卡顿或其他问题。

需要注意的是,使用这个后端你需要安装PyGTK。我不太清楚在Windows上还需要什么(因为我用的是Linux),但这似乎是最基本的要求。此外,如果你想默认使用这个后端,你需要在你的matplotlibrc文件中添加这一行(在Linux上,这个文件位于~/.matplotlib/matplotlibrc):

backend      : GTKAgg

如果你想使用其他后端,你需要参考官方的matplotlib示例,但这意味着你得构建一个迷你图形界面应用程序,才能运行一个简单的动画,我觉得这实在太麻烦了!

5

通常,图形用户界面(GUI)框架需要“掌控”程序的主循环。如果你在一个紧密的循环中加上延迟,这样做通常会导致GUI应用程序出现问题(你的问题描述和这种情况很一致)。可能matplotlib的开发者在后台做了一些处理,以防止某些工具包出现这种卡死的情况,但稍微调整一下你的程序结构应该能消除主循环掌控问题的可能性(我觉得这很有可能是问题所在)。matplotlib的动画文档也建议,对于一些复杂的操作,使用本地事件循环(可能就是为了这个原因)

与其在一个循环中加上延迟,不如使用GUI工具包来安排一个函数在一定时间后调用。

def update_function():
    # do frame calculation here

refresh_timer = QtCore.QTimer()
QtCore.QObject.connect( refresh_timer, QtCore.SIGNAL('timeout()'), update_function )
refresh_timer.start( 1.0 / 30 ) # have update_function called at 30Hz

查看matplotlib的文档,似乎可以直接使用他们的API,但我通过快速搜索没有找到好的例子。

撰写回答