未定义DISPLAY时,使用matplotlib生成PNG


319

我正在尝试将networkx与Python结合使用。当我运行该程序时,出现此错误。缺少什么吗?

#!/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

我现在收到另一个错误:

#!/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

我现在收到另一个错误:

#!/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


9
移动调用matplotlib.use(“此Agg”)你的其他进口上面,特别是它应该是matplotlib.pyplot的进口之前
伊沃Bosticky

@IvoBosticky评论也为我解决了这个问题:唯一令人误解的是“在其他进口商品之上”。很明显,您需要先导入matplotlib ...这是对我有用的整个设置:import matplotlib // matplotlib.use('Agg')// import matplotlib.pyplot as plt
mrk 2015年

Answers:


518

主要问题是(在您的系统上)matplotlib默认情况下选择使用x的后端。我在其中一台服务器上遇到了同样的问题。对我来说,解决方案是任何其他pylab / matplotlib / pyplot导入之前先读取的位置添加以下代码:

import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('Agg')

另一种方法是在您的.matplotlibrc中进行设置


182
重要说明:导入pyplot之前,需要先调用.use。因此,例如,如果您只是尝试导入pyplot,则需要先导入matplotlib,调用use,然后再导入pyplot。
seaotternerd

8
上面的评论将通过此答案得到更多的解释。
Ioannis Filippidis 2014年

2
您如何“在您的.matplotlibrc中设置它”?
tommy.carstensen

18
backend: agg~/.config/matplotlib'/matplotlibrc(作为一个例子,seehttp://matplotlib.org/faq/troubleshooting_faq.html#locating-matplotlib-config-dir)。另请参见matplotlib.org/users/customizing.html,其底部有一个示例配置文件。在该页面上找到“ agg”,您将看到所需的配置选项。
Reinout van Rees 2015年

4
供参考,这是解释此内容的matplotlib文档的链接。(+1,很好的答案,对我帮助很大!)
蒂姆·S.

72

只是对Reinout的回答的补充。

解决此类问题的永久方法是编辑.matplotlibrc文件。通过找到它

>>> import matplotlib
>>> matplotlib.matplotlib_fname() # This is the file location in Ubuntu '/etc/matplotlibrc'

然后将该文件中的后端修改为backend : Agg。这就对了。


5
临提示:设置$MATPLOTLIBRC目录,你想抛出自己的matplotlibrc英寸
肯尼斯Hoste先生

有点像这样的问题,Kinda会大吃一惊,但是我想如果服务器始终没有工作,那么修改配置文件是有意义的。这会对matplotlib的功能产生任何副作用吗?
BruceJohnJennerLawso

我在Web服务器上运行matplotlib,所以这就是我的答案。我还没有注意到任何副作用。
spitz

42

明确的答案是花一些时间正确准备执行环境。

你必须准备执行环境第一种方法是使用一个matplotlibrc文件,明智地由克里斯Q.建议,设置

backend : Agg

在那个文件中。您甚至可以控制matplotlib查找和查找matplotlibrc文件的方式和位置,而无需更改代码。

准备执行环境的第二种技术是使用MPLBACKEND环境变量(并通知您的用户使用它):

export MPLBACKEND="agg"
python <program_using_matplotlib.py>

这很方便,因为您甚至不必在磁盘上提供另一个文件即可完成此工作。我采用了这种方法,例如进行持续集成测试,并在没有显示器的远程计算机上运行。

在您的Python代码中将matplotlib后端硬编码为“ Agg”,就像用大铁锤将方钉砸成一个圆孔,相反,您本可以告诉matplotlib它必须是方孔。


在这种情况下,第二种技术看起来最优雅。
德米特里·卡巴诺夫

使用MPLBACKEND为我解决了它。绝对是最优雅的方式!
SaturnFromTitan

41

通过Spark使用matplotlib时出现错误。matplotlib.use('Agg')对我不起作用。最后,以下代码对我有用。这里更多

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

这很好用,而对用于导入matplotlib和其他库的顺序没有限制。
PabTorre

在Spark上运行时,是否必须限制它在头节点上运行,还是在工作程序节点上运行时使它工作?
萨卡

我在django项目中使用了它,这是我可以使其工作的唯一方法。
HenryM

31

我将重复@Ivo Bosticky所说的话,但可以忽略。将这些行放在py文件的非常开头。

import matplotlib
matplotlib.use('Agg') 

否则会出错

* / usr / lib / pymodules / python2.7 / matplotlib / __ init__.py:923:UserWarning:此对matplotlib.use()的调用无效
因为已经选择了后端;
必须在pylab,matplotlib.pyplot,*之前调用matplotlib.use()

这将解决所有显示问题


15

我发现此片段在X和非X环境之间切换时效果很好。

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

我认为,尽管它不能直接回答问题,也可以回答未提出的问题,但它是一种比接受的解决方案更好的解决方案。
荒木大辅

14

登录服务器以执行代码时,请改用以下命令:

ssh -X username@servername

-X将摆脱没有显示名称并且没有$ DISPLAY环境变量错误

:)


1
我需要使用'-X'来保存.png图像。非常感谢。
2012年

如果ssh超时,或者由于某种原因需要断开连接,则将导致长时间的失败。请注意,如果连接的客户端进入睡眠状态,甚至可能会发生超时。
posdef

您可以通过添加超时来防止超时,-o ServerAliveCountMax=120 -o ServerAliveInterval=30这将使ssh客户端每30秒发送一个空数据包,最长1小时。
亚历克斯(Alex)

5

您在什么系统上?看起来您的系统具有X11,但未正确设置DISPLAY环境变量。尝试执行以下命令,然后重新运行程序:

export DISPLAY=localhost:0

但是为什么需要设置显示变量,我远程登录到该服务器,它应该做的就是生成一个PNG文件???
krisdigitx

1
@krisdigitx,如果您已远程连接,请不要设置显示变量;而是在连接时使用“ -XY”标志。为了显示,它需要知道将图像发送到哪个Xserver。在这种情况下,它将是您计算机的显示器,而不是远程计算机。使用“ -XY”标志会使SSH自动将DISPLAY变量设置为指向连接计算机的显示。
Michael Aaron Safyan

@krisdigitx,我同意,这样做很奇怪;我的猜测是,它使用X11绘制图像,然后使用X11保存结果。
Michael Aaron Safyan

使用$ DISPLAY的此设置在运行Ubuntu 16的EC2上不起作用–无法连接以显示“ localhost:0”
PabTorre

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

这个对我有用。


3

要检查的另一件事是您当前的用户是否有权连接到X显示器。在我的情况下,不允许root执行此操作,并且matplotlib抱怨同样的错误。

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

来源:http : //www.debian-administration.org/articles/494 https://debian-administration.org/article/494/Getting_X11_forwarding_through_ssh_working_after_running_su


2

为了确保您的代码可在Windows,Linux和OSX上移植,以及对于带有和不带有显示器的系统,我建议使用以下代码段:

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

信用:https : //stackoverflow.com/a/45756291/207661


1

对于Google Cloud Machine Learning Engine:

import matplotlib as mpl
mpl.use('Agg')
from matplotlib.backends.backend_pdf import PdfPages

然后打印到文件:

#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()

并创建PDF:

multi_page(report_name)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.