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.