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-using 백엔드를 선택한다는 것입니다. 내 서버 중 하나에서 동일한 문제가 발생했습니다. 나를위한 해결책은 다른 pylab / matplotlib / pyplot 가져 오기 전에 읽히는 곳에 다음 코드를 추가하는 것이 었습니다 .

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

대안은 .matplotlibrc에 설정하는 것입니다


182
중요 사항 : pyplot을 가져 오기 전에 .use를 호출해야합니다. 예를 들어 pyplot을 가져 오려는 경우 먼저 matplotlib를 가져 와서 사용을 호출하고 pyplot을 가져와야합니다.
seaotternerd

8
위의 설명은 이 답변에 의해 더 설명됩니다 .
Ioannis Filippidis

2
".matplotlibrc에서 어떻게 설정합니까?"
tommy.carstensen

18
backend: agg~/.config/matplotlib'/matplotlibrc(: //matplotlib.org/faq/troubleshooting_faq.html#locating-matplotlib-config-dir 예로서 http://code.google.com/apis/earth/documentation/releasenotes.html을 참조). 페이지 하단에 구성 파일 예제가있는 matplotlib.org/users/customizing.html 도 참조 하십시오. 해당 페이지에서 "agg"를 찾으면 필요한 구성 옵션이 표시됩니다.
Reinout van Rees

4
참고로, 여기에 이것을 설명하는 matplotlib 문서에 대한 링크 가 있습니다. (+1, 큰 대답은 나를 완벽하게 도와주었습니다!)
Tim S.

72

Reinout의 답변을 보완하는 것과 같습니다.

이런 종류의 문제를 해결하는 영구적 인 방법은 .matplotlibrc 파일을 편집하는 것입니다. 통해 찾기

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

그런 다음 해당 파일의 백엔드를로 수정하십시오 backend : Agg. 그게 다야.


5
프로 팁 : 설정 $MATPLOTLIBRC받는 디렉토리 당신이 당신의 자신의 matplotlibrc을 던져합니다.
케네스 Hoste을

이런 문제로 과잉 살해했지만 서버가 항상 헤드리스로 작동하면 구성 파일을 수정하는 것이 좋습니다. matplotlib의 기능에 부작용이 있습니까?
BruceJohnJennerLawso

웹 서버에서 matplotlib를 실행 중이므로 이것이 대답이었습니다. 부작용이 없었습니다.
spitz

42

정답은 실행 환경을 올바르게 준비하는 데 약간의 시간이 걸립니다.

당신이 당신의 실행 환경을 준비해야 할 첫 번째 기술은 사용하는 matplotlibrc파일 로 현명 크리스 Q. 추천을 설정,

backend : Agg

그 파일에. matplotlib가 파일을 찾고 찾는 방법과 위치를 코드 변경없이 제어 할 수도 있습니다.matplotlibrc .

실행 환경을 준비해야하는 두 번째 기술은 MPLBACKEND환경 변수 를 사용하고 사용자에게 환경 변수 를 사용하도록 알리는 것입니다.

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

이 작업을 수행하기 위해 디스크에 다른 파일을 제공 할 필요가 없기 때문에 편리합니다. 예를 들어 지속적인 통합 테스트 및 디스플레이가없는 원격 컴퓨터에서 실행하는 등의 방법으로이 방법을 사용했습니다.

matplotlib 백엔드를 파이썬 코드에서 "Agg"로 하드 코딩하는 것은 큰 망치로 둥근 구멍에 사각형 페그를 강타하는 것과 같습니다. 대신 matplotlib에 사각형 구멍이 필요하다고 말할 수 있습니다.


두 번째 기술은이 상황에서 가장 우아해 보입니다.
Dmitry Kabanov

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 ()에 대한이 호출은 효과가 없습니다.
백엔드가 이미 선택 되었기 때문에;
matplotlib.use ()는 * pylab, matplotlib.pyplot, * 전에 호출되어야합니다. *

모든 디스플레이 문제가 해결됩니다.


15

X와 no-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
.png 이미지를 저장하려면 '-X'를 사용해야합니다. 많은 감사합니다.
nos

ssh가 시간 초과되거나 어떤 이유로 든 연결을 끊어야하는 경우 긴 프로세스 동안 실패합니다. 연결 클라이언트가 휴면 상태 인 경우에도 시간 종료가 발생할 수 있습니다.
posdef

-o ServerAliveCountMax=120 -o ServerAliveInterval=30ssh 클라이언트가 최대 1 시간 동안 30 초마다 빈 패킷을 보내도록하는 시간 초과를 방지 할 수 있습니다 .
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

Ubuntu 16을 실행하는 EC2에서는 $ DISPLAY에이 설정을 사용할 수 없습니다. "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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.