@H_403_1@请考虑直接从Matplotlib文档中获取的以下代码:
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.animation as animation
- import time # optional for testing only
- import cv2 # optional for testing only
- fig = plt.figure()
- def f(x,y):
- return np.sin(x) + np.cos(y)
- x = np.linspace(0,2 * np.pi,120)
- y = np.linspace(0,100).reshape(-1,1)
- im = plt.imshow(f(x,y),animated=True)
- def updatefig(*args):
- global x,y
- x += np.pi / 15.
- y += np.pi / 20.
- im.set_array(f(x,y))
- return im,ani = animation.FuncAnimation(fig,updatefig,interval=50,blit=True)
- plt.show()
这在我的系统上工作正常.现在,尝试将以下代码附加到上面的代码中:
- while True:
- #I have tried any of these 3 commands,without success:
- pass
- #time.sleep(1)
- #cv2.waitKey(10)
结果是该程序冻结了.显然,Matplotlib的“Animation”类在一个单独的线程中运行动画.所以我有以下两个问题:
1)如果进程在一个单独的线程中运行,为什么它会受到后续循环的干扰?
2)如何对python说等到动画结束?
解决方法
对我来说,复制到ipython按预期工作(动画首先播放然后是无限循环)但是在运行脚本时它会冻结.
1)我不确定cpython究竟是如何处理多线程的,特别是当与特定的matplotlib后端结合使用时,它似乎在这里失败了.一种可能性是通过使用来明确你想如何使用线程
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.animation as animation
- import multiprocessing as mp
- fig = plt.figure()
- def f(x,#A function to set thread number 0 to animate and the rest to loop
- def worker(num):
- if num == 0:
- ani = animation.FuncAnimation(fig,blit=True)
- plt.show()
- else:
- while True:
- print("in loop")
- pass
- return
- # Create two threads
- jobs = []
- for i in range(2):
- p = mp.Process(target=worker,args=(i,))
- jobs.append(p)
- p.start()
它定义了两个线程并设置一个用于动画,一个用于循环.
2)为了解决这个问题,正如@Mitesh Shah所建议的那样,你可以使用plt.show(block = True).对我来说,脚本然后按照预期的方式运行动画然后循环.完整代码:
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.animation as animation
- fig = plt.figure()
- def f(x,blit=True)
- plt.show(block=True)
- while True:
- print("in loop")
- pass
更新:替代方案是简单地使用交互模式,
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.animation as animation
- fig = plt.figure()
- plt.ion()
- plt.show()
- def f(x,y):
- return np.sin(x) + np.cos(y)
- def updatefig(*args):
- global x,y
- x = np.linspace(0,1)
- im = plt.imshow(f(x,y))
- for i in range(500):
- x += np.pi / 15.
- y += np.pi / 20.
- im.set_array(f(x,y))
- plt.draw()
- plt.pause(0.0000001)