【问题标题】:Python animation figure window cannot be closed automaticallyPython动画人物窗口无法自动关闭
【发布时间】:2017-05-04 16:20:41
【问题描述】:

使用matplotlib.animation创建动画并保存时,尝试通过plt.close关闭图形窗口时出现错误:

Python 版本:

Python 2.7.12 |Anaconda 自定义(64 位)| (默认,2016 年 7 月 2 日,17:42:40)
IPython 4.1.2 -- 增强的交互式 Python

目前我切换到使用 PyCharm 2017.1 社区版。当在 IPython 中从 %cpaste 或 %paste 运行或使用 Shift+Alt+E 在 PyCharm 的交互式控制台中运行时,可以直接在 IPython 和 PyCharm 中重现错误消息。使用的电影编码器是集成在 mplayer 中的 mencoder,因为这是我工作场所安装的默认编码器。

注意:

  • 在 IPython 中首先使用plt.ion() 开启交互模式(在 PyCharm 中已经默认开启)
  • 使用鼠标中键将代码直接粘贴到 IPython 屏幕时,代码在 IPython 中退出且不会出错
  • 单独输入所有命令以及粘贴(%cpaste、%paste)除plt.close() 之外的所有命令然后手动输入plt.close() 时,代码在 IPython 或 PyCharm 中无错误退出
  • 将plt.close() 替换为plt.clf() 时,代码无错误退出,但我需要plt.close(),例如用于在需要从头开始重新创建图形的不同参数的循环中创建动画
  • 在脚本中从头到尾运行代码时代码无错误退出(非交互模式)
  • 用鼠标点击窗口按钮关闭图形窗口时,代码无错误退出
  • 在plt.close() 之前插入time.sleep(1) 时代码退出with错误,因此问题可能与代码中的时间冲突无关

下面给出了一个最小、完整且(希望)可验证的示例:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# animation function for random image data
def animate_random_data(i):
    new_data = np.random.rand(10, 10)
    # update the data
    im.set_data(new_data)

# initialize the graph
first_data = np.random.rand(10,10)
im = plt.imshow(first_data,interpolation='none')
myfig = plt.gcf()

# create the animation and save it
ani = animation.FuncAnimation(myfig, animate_random_data, range(10), 
                              interval=100)
ani.save('animation_random_data.mpg', writer='mencoder')
plt.close()

错误回溯(来自 PyCharm):

Traceback (most recent call last):  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 176, in __draw_idle_agg
    FigureCanvasAgg.draw(self)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 474, in draw
    self.figure.draw(self.renderer)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/figure.py", line 1165, in draw
    self.canvas.draw_event(renderer)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 1809, in draw_event
    self.callbacks.process(s, event)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/cbook.py", line 563, in process
    proxy(*args, **kwargs)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/cbook.py", line 430, in __call__
    return mtd(*args, **kwargs)  
  File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/animation.py", line 652, in _start
    self.event_source.add_callback(self._step)  
AttributeError: 'NoneType' object has no attribute 'add_callback'

尽管程序在手动关闭窗口时如上列表中所述继续而没有错误,但这是一个令人讨厌的错误(想想循环中的多个动画)。该错误也出现在例如一维线图。感谢您的帮助(并澄清此错误消息的确切含义)!

【问题讨论】:

    标签: python animation matplotlib plot


    【解决方案1】:

    错误来自关闭图形时仍在运行的动画。虽然在大多数情况下,关闭图形时会自动停止动画,但在交互模式下似乎并非如此。

    解决方案可以是显式停止动画并在关闭图形之前将其删除。

    ani = animation.FuncAnimation(...)
    ani.save(...)
    ani.event_source.stop()
    del ani
    plt.close()
    

    【讨论】:

    • 有趣的是,ani.event_source.stop() 在直接输入时会在交互模式下停止动画,但在粘贴时不会。如果之后使用del ani,则在粘贴动画的情况下会在特定帧处停止。还要考虑没有del ani,plt.close() 仍然给出与以前相同的错误,但包括这两行都有效。
    • 评论已被接受为答案,因为建议的方法可以防止错误消息。但是,我仍然不明白,为什么在关闭窗口之前停止动画是不够的。
    【解决方案2】:

    在这种情况下,您可以使用 exit() 退出程序

    【讨论】:

    • 退出将不允许循环中的多个动画,正如问题所指定的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多