DISPLAYが定義されていないときにmatplotlibを使用してPNGを生成する


319

Pythonでnetworkxを使用しようとしています。このプログラムを実行すると、このエラーが発生します。不足しているものはありますか?

#!/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のインポートの前でなければなりません
Ivo Bosticky

@IvoBostickyコメントも私にとってそれを解決しました:誤解を招く唯一のものは、「他のインポートより上」です。以前にmatplotlibをインポートする必要があることは明らかです...これは私のために働いた全体の設定です:import matplotlib // matplotlib.use( 'Agg')// matplotlib.pyplotをpltとしてインポート
mrk

回答:


518

主な問題は、(システム上で)matplotlibがデフォルトでxを使用するバックエンドを選択することです。サーバーの1つで同じ問題が発生しました。私のための解決策は、他の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 2013年

8
上記のコメントは、この回答で詳しく説明されています
Ioannis Filippidis 2014

2
どのように「.matplotlibrcに設定」しますか?
tommy.carstensen 2015

18
backend: agg~/.config/matplotlib'/matplotlibrc(://matplotlib.org/faq/troubleshooting_faq.html#locating-matplotlib-config-dir例として、seehttp)。ページの下部に設定ファイルの例があるmatplotlib.org/users/customizing.htmlも参照してください。そのページで「agg」を見つけると、必要な構成オプションが表示されます。
Reinout van Rees、2015

4
参考までに、これはこれを説明するmatplotlibドキュメントへのリンクです。(+1、すばらしい答え、私を完全に助けてくれました!)
Tim S.

72

ラインアウトの答えを補完するものとして。

この種の問題を解決する永続的な方法は、.matplotlibrcファイルを編集することです。経由してそれを見つける

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

次に、そのファイルのバックエンドをに変更しますbackend : Agg。それだ。


5
プロヒント:設定$MATPLOTLIBRCたディレクトリ。あなたはあなた自身のmatplotlibrcをスローするようにしたい
ケネスHoste

このような問題ではちょっとやりすぎですが、サーバーが常にヘッドレスで動作している場合は、構成ファイルを変更するのが理にかなっていると思います。これは、matplotlibが機能する方法に副作用がありますか?
BruceJohnJennerLawso 2016

私はウェブサーバーでmatplotlibを実行しているので、これが私の答えでした。私は副作用に気づきませんでした。
スピッツ

42

明確な答えは、実行環境を正しく準備するために少し時間をかけることです。

実行環境を準備するために必要な最初の手法は、Chris Qが賢明に推奨しているように、matplotlibrcファイルを使用することです設定

backend : Agg

そのファイルで。コードを変更することなく、matplotlibがmatplotlibrcファイルを検索する方法と場所を制御することもできます

実行環境を準備するために必要な2番目の手法は、MPLBACKEND環境変数を使用することです(そして、環境変数を使用するようユーザーに通知します)。

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

これを機能させるためにディスクに別のファイルを用意する必要がないので、これは便利です。私はこのアプローチを採用しており、たとえば、継続的インテグレーションでのテストや、ディスプレイのないリモートマシンでの実行などがあります。

Pythonコードでmatplotlibバックエンドを "Agg"にハードコーディングすることは、正方形のペグを大きなハンマーで丸い穴に打ち込むようなものです。


2番目の手法は、この状況で最もエレガントに見えます。
Dmitry Kabanov 2017年

MPLBACKENDを使用して解決しました。間違いなく最もエレガントな方法です!
SaturnFromTitan

41

Sparkからmatplotlibを使用しているときにエラーが発生しました。matplotlib.use('Agg')うまくいきません。結局、次のコードは私にとってはうまくいきます。詳細はこちら

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

これは、matplotlibおよびその他のライブラリをインポートするために使用される順序の制限なしで、うまく機能します。
PabTorre 2017

Sparkで実行しているときに、ヘッドノードで実行するように制限する必要がありましたか、それともワーカーノードで実行しているときにこれを機能させましたか?
Saca

私はこれをdjangoプロジェクトで使用していますが、これが動作させる唯一の方法でした。
HenryM 2018

31

見落とされがちな@Ivo Bostickyの発言を繰り返します。で、これらの行を入れて非常に PYファイルの開始。

import matplotlib
matplotlib.use('Agg') 

またはエラーが発生します

* / usr / lib / pymodules / python2.7 / matplotlib / __ init__.py:923:UserWarning:このmatplotlib.use()の呼び出しは効果がありません
バックエンドがすでに選択されているため。
matplotlib.use()はpylab、matplotlib.pyplot、*の前に呼び出す必要があります*

これですべてのディスプレイの問題が解決します


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

私の意見では、これは受け入れられた解決策よりも優れた解決策ですが、質問に直接答えることはなく、尋ねられなかった質問に答えます。
荒巻大輔2017

14

サーバーにサインインしてコードを実行する場合は、代わりにこれを使用します。

ssh -X username@servername

これ-Xにより、表示名と$ DISPLAY環境変数エラーがなくなります。

:)


1
.png画像を保存するには、「-X」を使用する必要があります。どうもありがとう。
nos

sshがタイムアウトした場合、または何らかの理由で切断する必要がある場合、これは長いプロセスで失敗します。接続しているクライアントがスリープ状態になった場合でも、タイムアウトが発生する可能性があることに注意してください。
posdef '13

-o ServerAliveCountMax=120 -o ServerAliveInterval=30sshクライアントが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

チェックするもう1つのことは、現在のユーザーが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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.