介绍
因为我来自 matlab ,我习惯了一个交互式界面,其中脚本可以在运行时更新图形。在处理过程中,每个图形都可以重新调整大小甚至关闭。这可能意味着每个图形都在自己的线程中运行,这显然不是 matplotlib 的情况。 .
IPython 可以使用魔术命令 %pylab
或 %matplotlib
来模仿 Matlab 的行为,它会做一些我还不明白的事情,而这正是我的重点问题。
然后我的目标是让独立的 Python 脚本像 Matlab 那样工作(或者像带有 %matplotlib
的 IPython 那样工作)。换句话说,我希望从命令行执行此脚本。我期待每 3 秒弹出一个新数字。在执行过程中,我将能够缩放、调整大小甚至关闭图形。
#!/usr/bin/python
import matplotlib.pyplot as plt
import time
def do_some_work():
time.sleep(3)
for i in range(10):
plt.plot([1,2,3,4])
plt.show() # this is way too boilerplate, I'd like to avoid it too.
do_some_work()
What alternative to
%matplotlib
I can use to manipulate figures while a script is running in Python (not IPython)?
我已经研究过哪些解决方案?
我目前找到了 3 种获取情节展示的方法。
<强>1。 %pylab
/%matplotlib
作为tom说,应该避免使用%pylab
,以防止命名空间被污染。
>>> %pylab
>>> plot([1,2,3,4])
这个解决方案很不错,情节是非阻塞的,不需要额外的 show()
,我仍然可以用 grid()
添加网格之后,我可以关闭、调整大小或缩放我的图形,而不会出现其他问题。
很遗憾,%matplotlib
命令仅在 IPython 上可用。
<强>2。 from pylab import *
或 from matplotlib.pyplot import plt
>>> from pylab import *
>>> plot([1,2,3,4])
这里的情况完全不同。我需要添加命令 show()
来显示我正在阻塞的图形。除了关闭图形以执行下一个命令(例如 grid()
),我什么也做不了,因为图形现在已关闭,所以这将无效...
** 3. from pylab import *
或 from matplotlib.pyplot import plt
+ ion()
**
一些建议建议使用 ion()
命令如下:
>>> from pylab import *
>>> ion()
>>> plot([1,2,3,4])
>>> draw()
>>> pause(0.0001)
不幸的是,即使绘图显示了,我也无法手动关闭图形。我需要在终端上执行 close()
,这不是很方便。此外还需要两个额外的命令,例如 draw();暂停(0.0001)
不是我所期望的。
总结
有了 %pylab
,一切都很棒,但我不能在 IPython 之外使用它
使用 from pylab import *
后跟 plot
,我得到了一个阻塞行为,IPython 的所有功能都被浪费了。
from pylab import *
后跟 ion
提供了一个很好的替代前一个的方法,但我必须使用奇怪的 pause(0.0001)
导致我无法手动关闭的窗口的命令(我知道某些后端不需要 pause
。我正在使用 WxAgg
,这是唯一有效的在 Cygwin x64
上运行良好。
这question建议使用 matplotlib.interactive(True)
。不幸的是,它不起作用,并提供与 ion()
相同的行为。
最佳答案
将您的 do_some_work
函数更改为以下内容,它应该可以工作。
def do_some_work():
plt.pause(3)
对于交互式后端 plt.pause(3)
启动事件循环 3 秒,以便它可以处理您的调整大小事件。注意 the documentation说这是一个实验功能,对于复杂的动画你应该使用 animation module .
%pylab
和 %matplotlib
魔术命令也会启动事件循环,这就是用户可以与绘图交互的原因。或者,您可以使用 %gui wx
启动事件循环,并使用 %gui
关闭它。您可以使用 IPython.lib.guisupport.is_event_loop_running_wx()函数来测试它是否正在运行。
使用ion()
或ioff()
的原因在'What is interactive mode' 中有很好的解释。页。原则上,没有 IPython 也可以进行用户交互。但是,我无法从该页面获取交互式示例以使用 Qt4Agg
后端,只能使用 MacOSX
后端(在我的 Mac 上)。我没有尝试使用 WX
后端。
编辑
我确实通过使用 PyQt4 而不是 PySide 设法让交互式示例与 Qt4Agg 后端一起工作(因此通过在我的 ~/.config/中设置
文件)。我认为该示例不适用于所有后端。我提交了一个问题 here .backend.qt4 : PyQt4
matplotlibrc
编辑2
恐怕我想不出一种在运行长时间计算时不使用线程来操纵图形的方法。正如您提到的:Matplotlib 不会启动线程,IPython 也不会。 %pylab 和 %matplotlib 命令在处理来自读取-评估-打印循环的命令和让 GUI 短时间处理事件之间交替。他们按顺序执行此操作。
事实上,即使使用 %matplotlib 或 %pylab 魔法,我也无法重现您的行为。 (明确一点:在 ipython
中,我首先调用 %matplotlib
,然后调用 %run yourscript.py
)。 %matplotlib 魔术将 Matplotlib 置于交互模式,这使得 plt.show()
调用非阻塞,以便立即执行 do_some_work
函数。但是,在 time.sleep(3)
调用期间,图形没有响应(如果我增加 sleep 时间,这会变得更加明显)。我不明白这在你这边是如何工作的。
除非我错了,否则您必须将计算分成更小的部分并使用 plt.pause
(或者更好的是,动画模块)来更新数字。
关于python - 如何在 Python 中运行脚本时操作图形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33696861/