194

Matplotlib seems to require the $DISPLAY environment variable which means a running X server.
Some web hosting services do not allow a running X server session.
Is there a way to generate graphs using matplotlib without a running X server?

[username@hostname ~]$ python2.6
Python 2.6.5 (r265:79063, Nov 23 2010, 02:02:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/username/lib/python2.6/matplotlib-1.0.1-py2.6-linux-i686.egg/matplotlib/pyplot.py", line 270, in figure
    **kwargs)
  File "/home/username/lib/python2.6/matplotlib-1.0.1-py2.6-linux-i686.egg/matplotlib/backends/backend_tkagg.py", line 80, in new_figure_manager
    window = Tk.Tk()
  File "/usr/local/lib/python2.6/lib-tk/Tkinter.py", line 1643, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
>>>
Joe Kington
  • 275,208
  • 71
  • 604
  • 463
Jonathan Livni
  • 101,334
  • 104
  • 266
  • 359

2 Answers2

360

@Neil's answer is one (perfectly valid!) way of doing it, but you can also simply call matplotlib.use('Agg') before importing matplotlib.pyplot, and then continue as normal.

E.g.

import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
fig.savefig('temp.png')

You don't have to use the Agg backend, as well. The pdf, ps, svg, agg, cairo, and gdk backends can all be used without an X-server. However, only the Agg backend will be built by default (I think?), so there's a good chance that the other backends may not be enabled on your particular install.

Alternately, you can just set the backend parameter in your .matplotlibrc file to automatically have matplotlib.pyplot use the given renderer.

xgdgsc
  • 1,367
  • 13
  • 38
Joe Kington
  • 275,208
  • 71
  • 604
  • 463
  • It seems insane to me that you have to import matplotlib twice. Is there an easier way? – tommy.carstensen Jul 05 '15 at 20:34
  • 14
    For what it's worth, you're not actually importing matplotlib twice. You're importing matplotlib and then importing a sub-module that's not automatically imported. There are other ways, yes (for example, change your `.maplotlibrc` file), that that's the most straight-forward one. – Joe Kington Jul 05 '15 at 20:39
  • what if I already imported pyplot ? can I still do it ? – Ciprian Tomoiagă Dec 18 '16 at 19:59
  • It stated "matplotlib.use() must be called *before* pylab, matplotlib.pyplot, or matplotlib.backends is imported for the first time." – xb. Sep 22 '17 at 15:20
  • Most backends you mentioned (specifically: pdf, ps, svg, agg) are non-GUI backends, so they do not allow to show the plot directly from the code. – Erel Segal-Halevi May 10 '20 at 08:39
  • this is incredibly simple and worked perfectly on WSL. thanks a lot. – Pronte Sep 14 '20 at 10:31
  • More specifically for the latter alternative, under Linux you just need to save `backend: Agg` in the file `.config/matplotlib/matplotlibrc` – nspo Dec 04 '20 at 12:00
  • I can easily do `mpl.use("Agg")` *after* importing any of the mentioned dependent packages, it just needs to be before *using* them. – bers Mar 30 '21 at 14:24
22

You need to use the matplotlib API directly rather than going through the pylab interface. There's a good example here:

http://www.dalkescientific.com/writings/diary/archive/2005/04/23/matplotlib_without_gui.html

Neil Vass
  • 5,251
  • 2
  • 22
  • 25
  • 3
    I'm working with `ssh` and `screen` and besides the `matplotlib.use('Agg')`suggestion this was the only solution that worked. Thanks for the contribution – user3085931 Jul 07 '16 at 09:25
  • 2
    @user3085931: Nice to know my answer's still useful to someone 5 years after I wrote it! Thanks for letting me know. – Neil Vass Jul 15 '16 at 08:01