====================
== Hi, I'm Vimiix ==
====================
Get hands dirty.

macOXS中使用matplotlib遇到的问题及探究

Python note matplotlib solution

第一次在 mac 系统上使用matplotlib库的时候,在执行的时候,往往会遇到下面这样的问题:

ImportError: Python is not installed as a framework. balabala....

解决方案

当然这个问题很好解决,网上有一搜就会找到如下两种解决方案:

第一种方案是在系统中设置

  • 假设你已经通过pip install matplotlib安装了 matplotlib,那么在你的根目录中会有一个名为〜/ .matplotlib的目录。
  • 在这个目录中创建一个matplotlibrc的文件 ,在里面添加一行代码:backend: TkAgg,保存退出即可。

总结为一行 shell 命令就是:echo "backend: TkAgg" >> ~/.matplotlib/matplotlibrc

这种方式可以设定整个系统的 matplotlib 渲染使用的引擎,但是不好的是,代码会变得不可移植,如果服务器很多,我们需要每一台机器都去设置这个参数,这时候就需要使用第二种方案。

第二种方案是在代码中设置

在引用matplotlib库的代码之前,添加如下两行代码(确认安装 TkInter):

import matplotlib
matplotlib.use('TkAgg')

这样也可以临时的修改前面提到的 backend变量。

为什么要这样做?

从两种解决方法基本可以看出,两种方法都是通过修改一个叫做 backend的值来解决的。但这个TKAgg是什么鬼呢?

回答这个问题就需要知道为什么会默认的情况会产生上面的那个 ImportError。出现这个错误的原因是,在 mac os 系统镜像中渲染 matplotlib 的后端,默认情况下使用的是Cocoa的 API 来渲染。其实还有 Qt4AggGTKAggTkAgg等很多可以使用。这是 macosx 与其他 windows 或 linux os 相比不同的地方。

什么是backend

网上有很多的文档或解决方案都会提到backend,但许多用户对此术语会感到困惑(比如我)。matplotlib 会面对许多不同的用法和输出形式。比如,有人会在 python shell 交互使用 matplotlib,并在键入命令时弹出绘图窗口。有人将 matplotlib 嵌入到图形用户界面(如 wxpython 或 pygtk)中以构建丰富的应用程序。还有人在批处理脚本中使用 matplotlib 从一些数值模拟生成postscript 图像,还有一些是在 Web 应用程序服务器中生成 posts 动画以提供动态图形。

为了支持所有这些用法,matplotlib 可以提供不同的输出,这些输出中都称为backend; “frontend”是面向用户的代码,即绘图代码,而backend完成幕后的所有生成图形的复杂工作。

matplotlib 中有两种类型的backend

  • 用户界面后端(用于 pygtk,wxpython,tkinter,qt4 或 macosx 等,也被称为“交互式后端”)
  • 硬拷贝后端(用于制作图像文件 PNG,SVG,PDF,PS 等,也被称为“非交互式后端”)

设置backend的方法其实不止有网上提到两种方案,一共有四种方法。如果它们彼此有冲突,将使用以下列表中最后提到的方法,例如,调用use()则将会覆盖matplotlibrc中的设置。

  1. matplotlibrc文件中的backend参数,也就是我们上面说的方案一:

    (如果想定制化 matplotlib 其他的参数,点击查看):

backend : TkAgg   # Agg(antigrain) 渲染到 Tk canvas (需要安装TkInter)
  1. 为当前 shell 或单个脚本设置MPLBACKEND环境变量:
> export MPLBACKEND="module://my_backend"
> python simple_plot.py

> MPLBACKEND="module://my_backend" python simple_plot.py

设置此环境变量将覆盖 matplotlibrc 中的 backend 参数值,即使当前工作目录中存在 matplotlibrc 也是如此。因此,不鼓励在全局设置MPLBACKEND,例如在.bashrc.profile中,因为它会让我们很难发现问题。

  1. 要为单个脚本设置 backend,也可以使用 -d 命令行参数:
> python script.py -dbackend

不推荐使用此方法,因为-d参数可能与解析命令行参数的脚本冲突(参考issue#1986)。

  1. 如果你的脚本依赖于特定的后端,则可以使用use()函数:
import matplotlib
matplotlib.use('PS')   # 默认输出 postscript

如果要使用use()函数,则必须在导入matplotlib.pyplot之前调用。导入 pyplot 后调用use()将不起作用。如果想要使用不同的后端,则不得不对源码做编辑,修改use()中的代码来完成。因此,除非必要,否则应该避免显式调用use()

backend名称规范不区分大小写;例如,‘GTKAgg’和’gtkagg’是等价的。

backend选择列表

交互式列表

这些是支持的用户界面和渲染器组合,能够显示到屏幕并使用非交互式列表中的适当渲染器写入文件:

BackendDescription
GTKAggAgg rendering to a GTK 2.x canvas (requires PyGTK and pycairo or cairocffi; Python2 only)
GTK3AggAgg rendering to a GTK 3.x canvas (requires PyGObject and pycairo or cairocffi)
GTKGDK rendering to a GTK 2.x canvas (not recommended and d eprecated in 2.0) (requires PyGTK and pycairo or cairocffi; Python2 only)
GTKCairoCairo rendering to a GTK 2.x canvas (requires PyGTK and pycairo or cairocffi; Python2 only)
GTK3CairoCairo rendering to a GTK 3.x canvas (requires PyGObject and pycairo or cairocffi)
WXAggAgg rendering to to a wxWidgets canvas (requires wxPython)
WXNative wxWidgets drawing to a wxWidgets Canvas (not recommended and deprecated in 2.0) (requires wxPython)
TkAggAgg rendering to a Tk canvas (requires TkInter)
Qt4AggAgg rendering to a Qt4 canvas (requires PyQt4 or pyside)
Qt5AggAgg rendering in a Qt5 canvas (requires PyQt5)
macosxCocoa rendering in OSX windows (presently lacks blocking show() behavior when matplotlib is in non-interactive mode)

非交互式列表

以下是 matplotlib 渲染器的列表(每个渲染器都有一个同名支持,能够写入文件):

RendererFiletypesDescription
AGGpngraster graphics – high quality images using the Anti-Grain Geometry engine
PSps epsvector graphicsPostscript output
PDFpdfvector graphicsPortable Document Format
SVGsvgvector graphicsScalable Vector Graphics
Cairopng ps pdf svgvector graphicsCairo graphics
GDKpng jpg tiffraster graphics – the Gimp Drawing Kit Deprecated in 2.0

参考链接

— EOF —