在 Python shell 中使用 Matplotlib
默认情况下,matplotlib 将绘图延迟到脚本结束,因为绘图可能是开销大的操作,并且你可能不想在每次更改单个属性时更新绘图,而是只在所有属性更改后更新一次。
但是在 python shell 中工作时,通常需要用每个命令更新绘图,例如,在更改xlabel()或一行的标记样式之后。 虽然这在概念上很简单,但在实践中它可能很棘手,因为 matplotlib 在底层是一个图形用户界面应用程序,并拥有一些技巧,使应用程序在一个 python shell 正常工作。
使用 IPython 解决
注意
这里描述的模式出于历史原因仍然存在,但强烈建议不要使用。它污染函数的命名空间,会影响 python 内建设施,并可能导致错误难以跟踪。 要获得 IPython 集成而无需导入,使用%matplotlib魔术命令是首个选择。 参见 ipython 文档。
幸运的是,一个增强的交互式 python shell,ipython 已经找出了所有这些技巧,并且可被 matplotlib 感知,所以当你在 pylab 模式下启动 ipython。
johnh@flag:~> ipython
Python 2.4.5 (#4, Apr 12 2008, 09:09:16)
IPython 0.9.0 -- An enhanced Interactive Python.
In [1]: %pylab
Welcome to pylab, a matplotlib-based Python environment.
For more information, type 'help(pylab)'.
In [2]: x = randn(10000)
In [3]: hist(x, 100)
它为你设置一切使交互式绘图工作,就像你期望的那样。 调用figure()并弹出图形窗口,调用plot()使你的数据出现在图形窗口中。
注意在上面的例子中,我们没有导入任何 matplotlib 名称,因为在 pylab 模式下,ipython 将自动导入它们。 ipython 还为你启用交互模式,这会导致每个 pyplot 命令触发图形更新,并且还提供了一个 matplotlib 感知的运行命令,来高效运行 matplotlib 脚本。 ipython 在运行命令期间关闭交互模式,然后在运行结束时恢复交互状态,以便你可以手动继续调整图形。
ipython 已经嵌入了很多最近的作品,从 pylab 支持,到各种 GUI 应用程序,所以请检查 ipython 邮件列表的最新状态。
其它 Python 解释器
如果你不能使用 ipython,并且仍然想在交互式 python shell 使用 matplotlib/pylab,例如,plain-ole 标准的 python 交互式解释器,你将需要了解什么是 matplotlib 后端 。
有了 TkAgg 后端,它使用 Tkinter 用户界面工具包,你可以从任意的非 gui python shell 使用 matplotlib。 只需在你的matplotlibrc文件中设置backend : TkAgg和interactive : True(请参阅自定义 matplotlib)并启动 python。 然后:
>>> from pylab import *
>>> plot([1,2,3])
>>> xlabel('hi mom')
应该能够开箱即用。 这也可能适用于最新版本的 qt4agg 和 gtkagg 后端,以及 Macintosh 上的 macosx 后端。 注意,在批处理模式下,即从脚本制作图形时,交互模式可能很慢,因为它用每个命令重绘图形。 因此,你可能需要仔细考虑,然后通过matplotlibrc文件而不是使用下一节中列出的函数,使其作为默认行为。
Gui shell 问题最多,因为它们必须运行主循环,但是交互式绘图也涉及主循环。 Ipython 已经为 matplotlib 主后端解决了这一切问题。 可能有其他 shell 和 IDE 也可以在交互模式下使用 matplotlib,但一个明显的候选项不会:python IDLE IDE 是一个不支持 pylab 交互模式的 Tkinter gui 应用程序,无论后端是什么。
控制交互式更新
pyplot接口的interactive属性控制是否在每个pyplot命令上绘制图画布。 如果interactive是False,那么每个plot命令都会更新图形状态,但只会在显式调用draw()时绘制。 当interactive为True时,每个pyplot命令都会触发绘制。
pyplot接口提供了 4 个有助于交互式控制的命令。
isinteractive()
返回交互式设置。True|False。
ion()
将交互式模式打开。
ioff()
将交互式模式关闭。
draw()
强制图形重新绘制。
当处理绘图开销很大的大型图形时,你可能希望临时关闭 matplotlib 的交互式设置来避免性能损失:
>>> #create big-expensive-figure
>>> ioff() # turn updates off
>>> title('now how much would you pay?')
>>> xticklabels(fontsize=20, color='green')
>>> draw() # force a draw
>>> savefig('alldone', dpi=300)
>>> close()
>>> ion() # turn updating back on
>>> plot(rand(20), mfc='g', mec='r', ms=40, mew=4, ls='--', lw=3)