241

I am running a simple python script in the server:

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(60)
y = np.random.randn(60)

plt.scatter(x, y, s=20)

out_png = 'path/to/store/out_file.png'
plt.savefig(out_png, dpi=150)

I try to use the command python example.py in this server which has matplotlib 1.5.1 installed it fails with the error:

Traceback (most recent call last):
  File "example.py", line 7, in <module>
    plt.scatter(x, y, s=20)
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/pyplot.py", line 3241, in scatter
    ax = gca()
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/pyplot.py", line 928, in gca
    return gcf().gca(**kwargs)
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/pyplot.py", line 578, in gcf
    return figure()
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/pyplot.py", line 527, in figure
**kwargs)
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 84, in new_figure_manager
    return new_figure_manager_given_figure(num, figure)
  File "/home/USER/.virtualenvs/nnet/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 92, in new_figure_manager_given_figure
    window = Tk.Tk()
  File "/usr/local/lib/python2.7/lib-tk/Tkinter.py", line 1810, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

What is happening here?

Serenity
  • 35,289
  • 20
  • 120
  • 115
Po-Yu Kao
  • 2,597
  • 2
  • 12
  • 14

11 Answers11

346

Matplotlib chooses Xwindows backend by default. You need to set matplotlib to not use the Xwindows backend.

Add this code to the start of your script (before importing pyplot) and try again:

import matplotlib
matplotlib.use('Agg')

Or add to .config/matplotlib/matplotlibrc line backend: Agg to use non-interactive backend.

echo "backend: Agg" > ~/.config/matplotlib/matplotlibrc

Or when connect to server use ssh -X remoteMachine command to use Xwindows.

Also you may try to export display: export DISPLAY=mymachine.com:0.0.

For more info: https://matplotlib.org/faq/howto_faq.html#matplotlib-in-a-web-application-server

Serenity
  • 35,289
  • 20
  • 120
  • 115
  • 14
    'ssh -X remoteMachine' solved my problem. Thank you! – Po-Yu Kao Jun 04 '16 at 00:25
  • 8
    what is 'Agg' in fact? – CKM Nov 09 '17 at 11:08
  • 8
    AGG is the abbreviation of Anti-grain geometry engine. – Serenity Nov 10 '17 at 01:22
  • 7
    `matplotlib.use('Agg')` works for me - running inside a Docker image. – Mattia Paterna Mar 08 '18 at 08:39
  • This one solved my problem. I'm running on Google cloud VMs, hope this helps people have same issue. – Demo Mar 26 '18 at 03:29
  • Still I am facing same issue in docker image. Could you share your docker file.? – user3639338 May 31 '18 at 04:13
  • `matplotlib.use('Agg')` works with AWS EC2 instances that are not running an Xwindows server or using the `ssh -X ...`. This is useful for using matplotlib in simple batch processing of data and plots. – Nick Settje Sep 05 '18 at 08:26
  • 1
    if you connect from Win machine to remote server via putty you have to install Xming to forward X11. – Serenity Feb 07 '19 at 01:44
  • I am trying `tkinter` on my vs code editor. It fails to generate a display image. Does vscode support producing images ? – Hayat Apr 11 '19 at 06:52
  • I added the two lines at the very beginning of my script, but it still does not work. However, when I switch to Python 3, it works. I have never seen this error until today though. – zyy Nov 01 '21 at 03:09
  • Shouldn't it be `echo "backend: Agg" >> ~/.config/matplotlib/matplotlibrc` to add the line without overwriting the file if it exist and has already some content? – Claudio Feb 05 '23 at 10:58
90

You can solve it by adding these two lines in the VERY beginning of your .py script.

import matplotlib
matplotlib.use('Agg')

PS: The error will still exists if these two lines are not added in the very beginning of the source code.

Horace Heaven
  • 712
  • 5
  • 13
  • 24
Qihui
  • 927
  • 6
  • 4
  • 23
    It should in the very beginning of the code. This is important. – hunter Sep 14 '17 at 08:26
  • this worked when running `matplotlib` on docker (no display attached), but what does it do actually? – loretoparisi Mar 07 '18 at 23:02
  • This works for me when I just run the python console on my vm, but the exact same code fails with the exact same error on the same vm when part of the running application. – rschwieb May 30 '18 at 17:42
  • But changing the backend from TkAgg to Agg in the config file did the trick. – rschwieb May 30 '18 at 18:01
64

To add up on the answer, I used this at the beginning of the needed script. So it runs smoothly on different environments.

import os
import matplotlib as mpl
if os.environ.get('DISPLAY','') == '':
    print('no display found. Using non-interactive Agg backend')
    mpl.use('Agg')
import matplotlib.pyplot as plt

Because I didn't want it to be alsways using the 'Agg' backend, only when it would go through Travis CI for example.

Sylhare
  • 5,907
  • 8
  • 64
  • 80
  • 5
    This solution has the added value to be the least intrusive one with whatever personal configuration one has. It should be higher. – jaumebonet Oct 17 '18 at 10:45
20

I had this same issue trying to run a simple tkinter app remotely on a Raspberry Pi. In my case I did want to display the tkinter GUI on the pi display, but I want to be able to execute it over SSH from my host machine. I was also not using matplotlib, so that wasn't the cause of my issue. I was able to resolve the issue by setting the DISPLAY environment variable as the error suggests with the command:

export DISPLAY=:0.0

A good explanation of what the display environment variable is doing and why the syntax is so odd can be found here: https://askubuntu.com/questions/432255/what-is-display-environment-variable

ajgriese
  • 459
  • 5
  • 10
  • 27
    I am trying to save plots with python and matplotlib.pyplot running over ssh... doing this gets me: _tkinter.TclError: couldn't connect to display ":0.0" – mrk Jun 19 '17 at 13:37
  • For anyone who stumbles upon this: First you will want to find out what your actual display is with `echo $DISPLAY` (for me it was :10:0, i assume because I was connected via xrdp to see the output) through the console. Then, if you are coding remotely via remote-ssh, set the display with `export DISPLAY=` in the remote console and check that the xwindow host can access the display with `xhost +` – noel Jul 22 '23 at 22:00
9

I was facing it on Colab, and the following code lines solved it. Put it at the beginning of the notebook. Reference

### CREATE VIRTUAL DISPLAY ###
!apt-get install -y xvfb # Install X Virtual Frame Buffer
import os
os.system('Xvfb :1 -screen 0 1600x1200x16  &')    # create virtual display with size 1600x1200 and 16 bit color. Color can be changed to 24 or 8
os.environ['DISPLAY']=':1.0'    # tell X clients to use our virtual DISPLAY :1.0.
%matplotlib inline
### INSTALL GHOSTSCRIPT (Required to display NLTK trees) ###
!apt install ghostscript python3-tk
Vishal Gupta
  • 805
  • 14
  • 15
  • 1
    Just so others don't fall into the same trap I did: note when you execute xvfb, its name starts with a capital X! – snark May 05 '22 at 14:04
8

Another solution is to install Xvfb, and export your display to it. ie:

disp=:8
screen=0
geom=640x480x24
exec Xvfb $disp -screen $screen $geom 2>/tmp/Xvfb.log &

Then

$ export DISPLAY=:8

$ ./example.py

Joseph
  • 111
  • 1
  • 5
  • I'm running a code in Linux server, (it has tkinter, some GUI). Now, is there any way I can access this display other than VNC viewer or anything from my personal windows PC? – Adithya Swaroop Sep 29 '22 at 11:03
4

In order to see images, plots and anything displayed on windows on your remote machine you need to connect to it like this:

ssh -X user@hostname

That way you enable the access to the X server. The X server is a program in the X Window System that runs on local machines (i.e., the computers used directly by users) and handles all access to the graphics cards, display screens and input devices (typically a keyboard and mouse) on those computers.

More info here.

tsveti_iko
  • 6,834
  • 3
  • 47
  • 39
3

I also met this problem while using Xshell to connect Linux server.

After seaching for methods, I find Xming + Xshell to solve image imshow problem with matplotlib.

If solutions aboved can't solve your problem, just try to download Xming under the condition you're using Xshell. Then set the attribute in Xshell, SSH->tunnel->X11transfer->choose X DISPLAY localhost:0.0

Mode
  • 41
  • 2
2

I want to add an answer here that noone has explicitly stated with implementation.

This is a great resource to refer to for this failure: https://matplotlib.org/faq/usage_faq.html

In my case, using matplotlib.use did not work because it was somehow already set somewhere else. However, I was able to get beyond the error by defining an environment variable:

export MPLBACKEND=Agg

This takes care of the issue.

My error was in a CircleCI flow specifically, and this resolved the failing tests. One wierd thing was, my tests would pass when run using pytest, however would fail when using parallelism along with circleci tests split feature. However, declaring this env variable resolved the issue.

rrlamichhane
  • 1,435
  • 2
  • 18
  • 34
1

Though there is a solution use('Agg'), someone may be interested in solving x11.

So let's say we have a user ml, on ubuntu20 with python3...

First, log in as ml, and write a ml.py

$ cat ml.py
import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(60)
y = np.random.randn(60)

plt.scatter(x, y, s=20)

out_png = 'out_file.png'
plt.savefig(out_png, dpi=150)

Before run the file, we should set up x11,


$ whoami
ml

$ touch ~/.Xauthority

$ ls .Xauthority
.Xauthority

# only this one key is needed for X11 over SSH 
xauth generate :14 . trusted 

$ echo $DISPLAY
localhost:14.0

$ xauth list
ml/unix:14  MIT-MAGIC-COOKIE-1  b6a2833785df5e75e2c8bc34045a55a6

Run...

$ python3 ml.py
Matplotlib created a temporary config/cache directory at /tmp/matplotlib-rk288ipf because the default path (/home/ml/.config/matplotlib) is not a writable directory; it is highly recommended to set the MPLCONFIGDIR environment variable to a writable directory, in particular to speed up the import of Matplotlib and to better support multiprocessing.
Matplotlib is building the font cache; this may take a moment.
qt.qpa.xcb: X server does not support XInput 2
failed to get the current screen resources

Well, update OpenGL and x11-apps, rerun

$ python3 ml.py
Matplotlib created a temporary config/cache directory at /tmp/matplotlib-87at6bw8 because the default path (/home/zzx/.config/matplotlib) is not a writable directory; it is highly recommended to set the MPLCONFIGDIR environment variable to a writable directory, in particular to speed up the import of Matplotlib and to better support multiprocessing.
qt.qpa.xcb: X server does not support XInput 2
failed to get the current screen resources

Seems we can not get the out_file.png, but...

$ export QT_DEBUG_PLUGINS=1

And rerun the file, we get the image, :) out_file.png

LinconFive
  • 1,718
  • 1
  • 19
  • 24
-2

Try to use python 3, every problem are solved

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30591124) – Ailurophile Dec 15 '21 at 10:29