_tkinter.TclError: no display name and no $DISPLAY environment variable

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?


Solution 1:

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

Solution 2:

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.

Solution 3:

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.

Solution 4:

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

Solution 5:

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