问题
When creating an animation using matplotlib.animation and saving it, an error appears when trying to close the figure window via plt.close:
Python version:
Python 2.7.12 |Anaconda custom (64-bit)| (default, Jul 2 2016, 17:42:40)
IPython 4.1.2 -- An enhanced Interactive Python
Currently I switched to using PyCharm 2017.1 Community Edition. The error message can be reproduced both directly in IPython and within PyCharm when running from %cpaste
or %paste
in IPython or running in PyCharm's interactive console using Shift+Alt+E. The movie encoder used is mencoder as integrated in mplayer, since this is the default one installed at my work place.
Note:
- in IPython use
plt.ion()
first to turn on interactive mode (already switched on in PyCharm by default) - code exits without error in IPython when pasted using the middle mouse button directly into the IPython screen
- code exits without error in IPython or PyCharm when typing all commands separately and also when pasting (
%cpaste
,%paste
) all commands except forplt.close()
and then typingplt.close()
manually - code exits without error when replacing
plt.close()
withplt.clf()
, but I needplt.close()
, e.g. for creating animations in a loop with different parameters where the graph needs to be recreated from scratch - code exits without error when running the code in a script from start to end (non-interactive mode)
- code exits without error when closing the figure window clicking with the mouse on the window button
- code exits with error when inserting
time.sleep(1)
beforeplt.close()
, so the problem likely does not relate to time conflicts in the code
A minimal, complete and (hopefully) verifiable example is given below:
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()
Error traceback (from 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'
Although the program continues without error when closing the windows manually as written in the list above, it is an annoying bug (think of multiple animations in a loop). The error appears also for e.g. 1D line plots. Thanks for any help (and clarification on what this error message exactly means)!
回答1:
The error comes from the animation still running while closing the figure. While in most cases it is automatically taken care of to stop the animation when closing the figure, it seems not to be the case in interactive mode.
A solution can be to explicitely stop the animation and delete it before closing the figure.
ani = animation.FuncAnimation(...)
ani.save(...)
ani.event_source.stop()
del ani
plt.close()
回答2:
in this case you could just exit the program with exit()
来源:https://stackoverflow.com/questions/43776528/python-animation-figure-window-cannot-be-closed-automatically