我正在编写一个带有穿插的绘图和计算的python脚本。我对matplotlib的行为,特别是plt.pause
的必要性感到困惑。考虑以下片段:
import matplotlib.pyplot as plt
import time
fig,ax=plt.subplots()
ax.plot([1,2])
fig.show()
time.sleep(5) #This is a substitute for real computations
->在五秒钟内什么都没发生
import matplotlib.pyplot as plt
import time
fig,ax=plt.subplots()
ax.plot([1,2])
plt.pause(0.1)
fig.show()
time.sleep(5) #This is a substitute for real computations
->窗口显示所需绘图5秒
似乎需要plt.pause
才能看到任何东西。为什么文档中说"这个函数是实验性的;它的行为可能会在未来的版本中更改或扩展。"为什么我在任何教程中都没有看到plt.pause
此外,为什么如此重要的功能设计得如此奇怪,以至于用户必须输入足够小的时间,而不是零?我知道有些人真的想暂停性爱,但我没有,我只是想看看情节。这很不寻常吗?
顺便说一句,我注意到我也可以执行plt.show()
,由于我未知的原因,它的行为与plt.gcf().show()
[=fig.show
]不同,并阻止执行,直到用户关闭窗口。虽然这确实在我需要的时候显示了绘图,但我不希望执行停止,我希望用户在随后的计算过程中继续看到绘图。使用plt.show(block=False)
的行为看起来确实像plt.gcf().show()
[=fig.show()
],所以它也是无用的。
此外,我在某个地方读到plt.ion
应该有帮助,但它没有。在上面的代码段中,在fig,ax=plt.subplots()
之前添加plt.ion()
不会改变任何内容。
最后,我听说不同的后台可能会有不同的行为。我在Ubuntu 18上使用的是python 3.6(anaconda(和matplotlib 2.2.2。如果我在代码段的开头添加import matplotlib; matplotlib.use('Qt5Agg')
,没有太大的变化,但第一个代码段并没有在五秒钟内显示任何内容,而是显示了五秒钟的垃圾窗口(该窗口显示了屏幕上弹出位置显示的内容(。
来自plt.pause()
的文档
暂停几秒钟
如果有活动图形,它将在暂停前更新和显示,GUI事件循环(如果有(将在暂停期间运行
这可以用于粗糙的动画。有关更复杂的动画,请参阅matplotlib.animation.
因此pause
实际上将draw
作为图形。
plt.pause
之所以是"必需的",关键是它启动了模拟事件循环,这样它就有时间至少运行一次,并完整地生成图形。之后,您的代码可以继续。当代码运行时,不会处理任何进一步的事件。因此,该图形可能看起来没有响应。这意味着您应该在之后重复调用pause
,以免窗口冻结。通过这种方式,您可以模拟事件循环,同时仍然可以在其间运行其他代码。
plt.pause()
在该示例中被提及,其进行如上所述的操作。
fig.show()
不运行事件循环。因此,如果没有正在运行的事件循环,并且没有pause
,它将只显示图形窗口;但如果你不给任何时间来处理任何事件,它会立即冻结。在这里,您可能会体验到操作系统和后端之间的差异。也许你只看到窗口边框,中间什么也没画,或者你可能看到工具栏和白色表面。
一般来说,所有这些的关键是理解python(像其他编程语言一样(线性处理代码。希望运行一个事件循环,即一个响应GUI窗口,以及并行执行的其他一些代码与这一原则相矛盾。规避这种情况的常用方法是在不同的线程中运行任何其他代码。然而,matplotlib无法知道这是什么代码以及如何将其同步到主线程。因此,这样的解决方案需要用户来实现