如何在 matplotlib/Python 中更改后端

我纠结于下面这个问题。我需要生成由一组图表组成的报告。除了一个以外,所有这些图表都是使用 Matplotlib 默认后端(TkAgg)制作的。其中一个图表需要使用 Cairo 后端来绘制,原因是我正在绘制一个图形图,而这个图形只能使用 Cairo 来绘制。

问题是,我不能动态更改后端,例如下面的代码不起作用:
matplotlib.pyplot.switch_backend('cairo.png') (我知道 switch _ backend 功能是实验性的)

我也试过 matplotlib.use("cairo.png"),但是这会导致导入问题,因为 matplotlib.use("cairo.png")语句应该在导入 matplotlib.pyplot之前出现。 但在剧本的整个生命周期中,我需要两个不同的后端。

所以我的问题是,有人有一个代码片段,显示如何切换后端在 Matplotlib?

非常感谢!

更新: 我编写了一个加载 matplotlib、显示默认后端、卸载 matplotlib、重新加载它并更改后端的代码片段:

import matplotlib
import matplotlib.pyplot as plt
import sys
print matplotlib.pyplot.get_backend()


modules = []
for module in sys.modules:
if module.startswith('matplotlib'):
modules.append(module)


for module in modules:
sys.modules.pop(module)


import matplotlib
matplotlib.use("cairo.png")
import matplotlib.pyplot as plt


print matplotlib.pyplot.get_backend()

但这真的是解决问题的方法吗?

更新2: 我昨天有些严重的大脑冻结... 最简单和最明显的解决方案是使用开罗后端的所有图表,而不是切换后端:)

更新3: 事实上,这仍然是一个问题,所以任何人谁知道如何动态切换 matplotlib 后端... ... 请张贴您的答案。

120637 次浏览

So I am not completely sure if this is what you are looking for.

You can change your backend through the matplotlibrc file which contains certain configurations for your matplotlib.

In your script you can put:

matplotlib.rcParams['backend'] = 'TkAgg'

or something like that to switch between backends.

You could also have a different Python process make that plot, possibly with the help of pickle or joblib.

There is an "experimental" feature :

import matplotlib.pyplot as plt
plt.switch_backend('newbackend')

taken from matplotlib doc.

Switch the default backend to newbackend. This feature is experimental, and is only expected to work switching to an image backend. Eg, if you have a bunch of PostScript scripts that you want to run from an interactive ipython session, you may want to switch to the PS backend before running them to avoid having a bunch of GUI windows popup. If you try to interactively switch from one GUI backend to another, you will explode. Calling this command will close all open windows.

Why not just use the reload built-in function (importlib.reload in Python 3)?

import matplotlib
matplotlib.use('agg')


matplotlib = reload(matplotlib)
matplotlib.use('cairo.png')

Six years later and I came across a similar issue, when trying to decide which backend was available to use.
Note see Caveats - below

This code snippet works well for me:

import matplotlib
gui_env = ['TKAgg','GTKAgg','Qt4Agg','WXAgg']
for gui in gui_env:
try:
print("testing", gui)
matplotlib.use(gui,warn=False, force=True)
from matplotlib import pyplot as plt
break
except:
continue
print("Using:",matplotlib.get_backend())


Using: GTKAgg

As you can deduce, swapping the backend is as simple as re-importing matplotlib.pyplot after forcing the new backend

matplotlib.use('WXAgg',warn=False, force=True)
from matplotlib import pyplot as plt
print("Switched to:",matplotlib.get_backend())


Switched to: WXAgg

For those still having trouble, this code will print out the:
list of Non Gui backends;
the list of Gui backends;
and then attempt to use each Gui backend to see if it is present and functioning.

import matplotlib
gui_env = [i for i in matplotlib.rcsetup.interactive_bk]
non_gui_backends = matplotlib.rcsetup.non_interactive_bk
print ("Non Gui backends are:", non_gui_backends)
print ("Gui backends I will test for", gui_env)
for gui in gui_env:
print ("testing", gui)
try:
matplotlib.use(gui,warn=False, force=True)
from matplotlib import pyplot as plt
print ("    ",gui, "Is Available")
plt.plot([1.5,2.0,2.5])
fig = plt.gcf()
fig.suptitle(gui)
plt.show()
print ("Using ..... ",matplotlib.get_backend())
except:
print ("    ",gui, "Not found")

Caveats: Changes in matplotlib since version 3.3.0

  • The first parameter of matplotlib.use has been renamed from arg to backend (only relevant if you pass by keyword).
  • The parameter warn of matplotlib.use has been removed. A failure to switch the backend will now always raise an ImportError if force is set; catch that error if necessary.
  • All parameters of matplotlib.use except the first one are now keyword-only.

In my case (Windows 10 + python 3.7), the first answer by @Rolf of Saxony didn't work very well. Instead of trying all the available environments and configuring one of them at the beginning, i.e, just after

    import matplotlib

I had to change the environment from 'Agg' to 'TkAgg' using

    matplotlib.use('TKAgg',warn=False, force=True)

right before the code where I actually plotted, i.e,

    import matplotlib.pyplot as plt
fig = plt.figure()
# AND SO ON....

To permanently change the backend you can use this:

  1. First locate the matplotlibrc file:

    import matplotlib
    
    
    matplotlib.matplotlib_fname()
    # '/Users/serafeim/.matplotlib/matplotlibrc'
    
  2. Open the terminal and do:

    cd /Users/serafeim/.matplotlib/
    ls
    
  3. Edit the file (if it does not exist use this command: touch matplotlib to create it):

    vim matplotlibrc
    
  4. Add this line and save:

    backend: TkAgg
    

If you are using an IPython console (including within Spyder) you can use built-in magic commands to quickly switch backends, e.g.:

%matplotlib qt

Get a list of available backends to use with the command:

%matplotlib --list

Available matplotlib backends: ['tk', 'gtk', 'gtk3', 'wx', 'qt4', 'qt5', 'qt', 'osx', 'nbagg', 'notebook', 'agg', 'svg', 'pdf', 'ps', 'inline', 'ipympl', 'widget']

Extra Info

Although everyone show their own favorite back-end, it's quite messy to figure out what you need to install and what the requirements are. At least when you try to understand the generally confusing and technocratic documentation. Today I have made several experiments and think I have found the most simple solutions for each back-end to be able to plot with matplotlib in Windows and using Py3.8.5 (without Qt built-in). Here are my findings:

#--------------------------------------
# Installing the matplotlib backends
#--------------------------------------
# https://matplotlib.org/users/installing.html


pip install pycairo                     # [1] Cairo :   GTK3 based backend (replaces: cairocffi)    [1.2 Mb]
#pip install mplcairo                   # [1] Cairo :   Easy & Specific for matplotlib              [1.7 Mb]
#pip install PyQt5                      # [2] Qt5   :   Require: Qt's qmake tool                    []
pip install PySide2                     # [3] Qt5   :   Require: shiboken2 & Clang lib bindings     [136 Mb]
pip install wxPython                    # [4] WxAgg :   ??                                          [18.1 Mb]
pip install tornado                     # [5] WebAgg:   Require: pycurl,twisted,pycares ??          [422 kb]

Here are the links to all those PyPi's or Repos:

[1] https://pypi.org/project/pycairo/       # Requires GTK3+: https://www.gtk.org/
[1] https://pypi.org/project/mplcairo/      # https://github.com/matplotlib/mplcairo
[2] https://pypi.org/project/PyQt5/         #
[3] https://pypi.org/project/PySide2/       #
[4] https://pypi.org/project/wxPython/      # https://github.com/wxWidgets/Phoenix/
[4] https://github.com/wxWidgets/wxWidgets/releases
[5] https://pypi.org/project/tornado/       # https://github.com/tornadoweb/tornado

However, and very surprising given the vast quantities of documentation for using Tcl/Tk and the tkinter packages for python, I was not able to install it, nor find any useful instructions of how to import the the DLL's into python. (For linux this is trivial as you just use the OS package manager apt-get install <tk-what-not>, but this option is not available for windows, nor is there any simple analogue. Here is a list of the many and various binaries that you can get.

[6] http://www.bawt.tcl3d.org/download.html                 # Use Tcl-Pure (no additional packages)
[6] https://www.magicsplat.com/tcl-installer/index.html     #
[6] https://www.irontcl.com/                                #
[6] https://www.activestate.com/products/tcl/downloads/     #
[6] http://tclkits.rkeene.org/fossil/wiki/Downloads         #
[6] http://kitcreator.rkeene.org/kitcreator                 #

Perhaps someone can enlighten me as how to get any of these imported into python?


What backends are available and where?

Let's enlighten ourselves with the following one-liners:

python.exe -c "import matplotlib as m; help(m);"
python.exe -c "import matplotlib as m; print('I: {}\nN: {}'.format(m.rcsetup.interactive_bk,m.rcsetup.non_interactive_bk));"


# I: ['GTK3Agg', 'GTK3Cairo', 'MacOSX', 'nbAgg', 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo', 'TkAgg', 'TkCairo', 'WebAgg', 'WX', 'WXAgg', 'WXCairo']
# N: ['agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template']


python.exe -c "import matplotlib as m; p=m.get_backend();print('current backend is:',p);"
# agg


python.exe -c "import matplotlib as m; p=m.matplotlib_fname(); print('The matplotlibrc is located at:\n',p);"
# C:\Python38\lib\site-packages\matplotlib\mpl-data\matplotlibrc

Setting the back-end

As the documentation says: There are 3 ways to configure your backend:

  1. Setting the rcParams["backend"] (default: 'agg') parameter in your matplotlibrc file
  2. Setting the MPLBACKEND environment (shell) variable
  3. Using the function matplotlib.use()

Using the backend

Finally, to use your available backend is just a matter of doing this:

import matplotlib
#matplotlib.use('tkagg', force=True)        # Agg rendering to a Tk canvas
#matplotlib.use('wxcairo', force=True)      # Cairo rendering to a wxWidgets canvas
#matplotlib.use('wxagg', force=True)        # Agg rendering to a wxWidgets canvas
matplotlib.use('webagg', force=True)        # On show() will start a tornado server with an interactive figure.


#matplotlib.use('qt5cairo', force=True)     # Cairo rendering to a Qt5 canvas
#matplotlib.use('qt5agg', force=True)       # Agg rendering to a Qt5 canvas


import matplotlib.pyplot as plt