Generating a PNG with matplotlib when DISPLAY is undefined
I am trying to use networkx with Python. When I run this program it get this error. Is there anything missing?
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
Traceback (most recent call last):
File "graph.py", line 13, in <module>
nx.draw(G)
File "/usr/lib/pymodules/python2.5/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
I get a different error now:
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
matplotlib.use('Agg')
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
/usr/lib/pymodules/python2.5/matplotlib/__init__.py:835: UserWarning: This call to matplotlib.use() has no effect
because the the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
File "graph.py", line 15, in <module>
nx.draw(G)
File "/usr/lib/python2.5/site-packages/networkx-1.2.dev-py2.5.egg/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
I get a different error now:
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
matplotlib.use('Agg')
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
/usr/lib/pymodules/python2.5/matplotlib/__init__.py:835: UserWarning: This call to matplotlib.use() has no effect
because the the backend has already been chosen;
matplotlib.use() must be called *before* py开发者_StackOverflow社区lab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
File "graph.py", line 15, in <module>
nx.draw(G)
File "/usr/lib/python2.5/site-packages/networkx-1.2.dev-py2.5.egg/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
The main problem is that (on your system) matplotlib chooses an x-using backend by default. I just had the same problem on one of my servers. The solution for me was to add the following code in a place that gets read before any other pylab/matplotlib/pyplot import:
import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('Agg')
The alternative is to set it in your .matplotlibrc
Just as a complement of Reinout's answer.
The permanent way to solve this kind of problem is to edit .matplotlibrc file. Find it via
>>> import matplotlib
>>> matplotlib.matplotlib_fname()
# This is the file location in Ubuntu
'/etc/matplotlibrc'
Then modify the backend in that file to backend : Agg
. That is it.
The clean answer is to take a little bit of time correctly prepare your execution environment.
The first technique you have to prepare your execution environment is to use a matplotlibrc
file, as wisely recommended by Chris Q., setting
backend : Agg
in that file. You can even control — with no code changes — how and where matplotlib looks for and finds the matplotlibrc
file.
The second technique you have to prepare your execution environment is to use the MPLBACKEND
environment variable (and inform your users to make use of it):
export MPLBACKEND="agg"
python <program_using_matplotlib.py>
This is handy because you don't even have to provide another file on disk to make this work. I have employed this approach with, for example, testing in continuous integration, and running on remote machines that do not have displays.
Hard-coding your matplotlib backend to "Agg" in your Python code is like bashing a square peg into a round hole with a big hammer, when, instead, you could have just told matplotlib it needs to be a square hole.
I got the error while using matplotlib through Spark. matplotlib.use('Agg')
doesn't work for me. In the end, the following code works for me. More here
import matplotlib.pyplot as plt.
plt.switch_backend('agg')
I will just repeat what @Ivo Bosticky said which can be overlooked. Put these lines at the VERY start of the py file.
import matplotlib
matplotlib.use('Agg')
Or one would get error
*/usr/lib/pymodules/python2.7/matplotlib/__init__.py:923: UserWarning: This call to matplotlib.use() has no effect because the the backend has already been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot,*
This will resolve all Display issue
I found this snippet to work well when switching between X and no-X 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
When signing into the server to execute the code use this instead:
ssh -X username@servername
the -X
will get rid of the no display name and no $DISPLAY environment variable
error
:)
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
It works for me.
What system are you on? It looks like you have a system with X11, but the DISPLAY environment variable was not properly set. Try executing the following command and then rerunning your program:
export DISPLAY=localhost:0
One other thing to check is whether your current user is authorised to connect to the X display. In my case, root was not allowed to do that and matplotlib was complaining with the same error.
user@debian:~$ xauth list
debian/unix:10 MIT-MAGIC-COOKIE-1 ae921efd0026c6fc9d62a8963acdcca0
root@debian:~# xauth add debian/unix:10 MIT-MAGIC-COOKIE-1 ae921efd0026c6fc9d62a8963acdcca0
root@debian:~# xterm
source: http://www.debian-administration.org/articles/494 https://debian-administration.org/article/494/Getting_X11_forwarding_through_ssh_working_after_running_su
To make sure your code is portable across Windows, Linux and OSX and for systems with and without displays, I would suggest following snippet:
import matplotlib
import os
# must be before importing matplotlib.pyplot or pylab!
if os.name == 'posix' and "DISPLAY" not in os.environ:
matplotlib.use('Agg')
# now import other things from matplotlib
import matplotlib.pyplot as plt
Credit: https://stackoverflow.com/a/45756291/207661
For Google Cloud Machine Learning Engine:
import matplotlib as mpl
mpl.use('Agg')
from matplotlib.backends.backend_pdf import PdfPages
And then to print to file:
#PDF build and save
def multi_page(filename, figs=None, dpi=200):
pp = PdfPages(filename)
if figs is None:
figs = [mpl.pyplot.figure(n) for n in mpl.pyplot.get_fignums()]
for fig in figs:
fig.savefig(pp, format='pdf', bbox_inches='tight', fig_size=(10, 8))
pp.close()
and to create the PDF:
multi_page(report_name)
import matplotlib
matplotlib.use('Agg')
worked for me as long as I was calling the plotting functions/code directly. But if you are using
from joblib import Parallel, delayed
Parallel
and delayed
modules for parallelizing your code then you need to add
matplotlib.rcParams.update({'backend': 'Agg'})
line inside your function in order for agg
backend to work.
精彩评论