2014-06-19 133 views
1

我在进程中运行动画分散。一切工作正常,除了当我想退出一切时抛出一个异常。在python(matplotlib)中优雅地停止(不暂停)动画剧情

import multiprocessing as mp 
import time 
from collections import deque 

def start_colored_scores(nb_channels): 
    q = mp.Queue() 
    process = mp.Process(target=colored_scores,args=(q,nb_channels,4000)) 
    process.start() 
    return process,q 

def colored_scores(q,nb_channels,size): 
    import matplotlib.pyplot as plt 
    import matplotlib.animation as animation 
    fig, axes = plt.subplots(nrows=nb_channels,ncols=1,sharex=True,sharey=True) 
    plt.axis([-1.0,1.0,-1.0,1.0]) 
    scats = [axe.scatter([0], [0], c="white", s=size) for axe in axes] 
    def animate(i): 
     scores = q.get() 
     if scores is None : # this is the external signal saying things should stop 
      plt.close() 
      return [axe.scatter([0], [0], c="white", s=size) for axe in axes] 
     scats = [] 
     for score,axe in zip(scores,axes): 
      score = max(min(1,1-score),0) 
      scats.append(axe.scatter([0], [0], c=(1-score,0,score), s=size)) 
     return scats 
    ani = animation.FuncAnimation(fig, animate, interval=1, blit=True) 
    plt.show() 

例如,这是工作的罚款:

_,q = start_colored_scores(2) 
x = 0 
right = 1 
time_start = time.time() 
while time.time()-time_start < 5: 
    if right==1 and x>1.0: 
     x = 1.0 
     right = -1 
    if right==-1 and x<0.0: 
     x = 0.0 
     right = 1 
    x+=right*0.02 
    q.put([x,1-x]) 
    time.sleep(0.02) 
q.put(None) # indicating I do not need plotting anymore 

print "this is printed ... exception in the process ?" 

的行为如我所料:显示和动画5秒散开,然后程序继续执行。唯一的问题是,抛出一个异常(我想在这个过程中)说:

AttributeError: 'NoneType' object has no attribute 'tk' 

有没有办法做同样的事情,但避免了异常?或者在某个地方发现这个异常?

+1

您可以添加完整的堆栈跟踪吗? – Nathaniel

回答

1

您可以捕获该异常很容易:

def colored_scores(q,nb_channels,size): 
    import matplotlib.pyplot as plt 
    import matplotlib.animation as animation 
    fig, axes = plt.subplots(nrows=nb_channels,ncols=1,sharex=True,sharey=True) 
    plt.axis([-1.0,1.0,-1.0,1.0]) 
    scats = [axe.scatter([0], [0], c="white", s=size) for axe in axes] 
    def animate(i): 
     scores = q.get() 
     if scores is None : # this is the external signal saying things should stop 
      plt.close() 
      return [axe.scatter([0], [0], c="white", s=size) for axe in axes] 
     scats = [] 
     for score,axe in zip(scores,axes): 
      score = max(min(1,1-score),0) 
      scats.append(axe.scatter([0], [0], c=(1-score,0,score), s=size)) 
     return scats 
    ani = animation.FuncAnimation(fig, animate, interval=1, blit=True) 
    try: 
     plt.show() 
    except AttributeError: # This will supress the exception 
     pass 

然而,一旦你的那一个,你会得到一个新的(至少在我的系统)陷阱:

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__ 
    return self.func(*args) 
    File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 536, in callit 
    func(*args) 
    File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 141, in _on_timer 
    TimerBase._on_timer(self) 
    File "/usr/lib/pymodules/python2.7/matplotlib/backend_bases.py", line 1203, in _on_timer 
    ret = func(*args, **kwargs) 
    File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 876, in _step 
    still_going = Animation._step(self, *args) 
    File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 735, in _step 
    self._draw_next_frame(framedata, self._blit) 
    File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 755, in _draw_next_frame 
    self._post_draw(framedata, blit) 
    File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 778, in _post_draw 
    self._blit_draw(self._drawn_artists, self._blit_cache) 
    File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 798, in _blit_draw 
    ax.figure.canvas.blit(ax.bbox) 
    File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 353, in blit 
    tkagg.blit(self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2) 
    File "/usr/lib/pymodules/python2.7/matplotlib/backends/tkagg.py", line 20, in blit 
    tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array)) 
TclError: this isn't a Tk application 

我可以找不到任何方法来压制那一个。你可以做什么,只是终止子,而不是试图将信号发送到关机:

proc,q = start_colored_scores(2) 
x = 0 
right = 1 
time_start = time.time() 
while time.time()-time_start < 5: 
    if right==1 and x>1.0: 
     x = 1.0 
     right = -1 
    if right==-1 and x<0.0: 
     x = 0.0 
     right = 1 
    x+=right*0.02 
    q.put([x,1-x]) 
    time.sleep(0.02) 
#q.put(None) # indicating I do not need plotting anymore 
proc.terminate() 

这不是通过队列发送的东西当作美丽的(并且不允许任何额外的清洁在子进程中,假设你想要它),但不会抛出任何异常。