DISPLAY tanımsız olduğunda matplotlib ile bir PNG oluşturma


319

Python ile networkx kullanmaya çalışıyorum. Bu programı çalıştırdığımda bu hatayı alıyorum. Eksik bir şey var mı?

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

Şimdi farklı bir hata alıyorum:

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

Şimdi farklı bir hata alıyorum:

#!/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
Çağrıyı diğer ithalatlarınızın üstünde matplotlib.use ('Agg')
öğesine taşıyın

@IvoBosticky yorum da benim için çözdü: Yanıltıcı olan tek şey "diğer ithalat üstünde". Daha önce matplotlib'i içe aktarmanız gerektiği açık olmalı ... Benim için çalışan tüm ayar budur: import matplotlib // matplotlib.use ('Agg') // import matplotlib.pyplot olarak plt
mrk

Yanıtlar:


518

Ana sorun (sisteminizde) matplotlib varsayılan olarak bir x-kullanarak arka uç seçmesidir. Aynı problemi sunucularımdan birinde de yaşadım. Benim için çözüm, diğer herhangi bir pylab / matplotlib / pyplot içe aktarmadan önce okunan bir yere aşağıdaki kodu eklemekti :

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

Alternatif .matplotlibrc içinde ayarlamak için


182
Önemli not: pyplot içe aktarılmadan önce .use çağrılmalıdır. Yani, örneğin, sadece pyplot'u almaya çalışıyorsanız, önce matplotlib'i içe aktarmanız, kullanımı çağırmanız ve daha sonra pyplot'u içe aktarmanız gerekir.
seaotternerd

8
Yukarıdaki yorum bu cevapla daha fazla açıklanmaktadır .
Ioannis Filippidis

2
".Matplotlibrc içine nasıl koyarsınız"?
tommy.carstensen

18
backend: aggiçinde ~/.config/matplotlib'/matplotlibrc(: //matplotlib.org/faq/troubleshooting_faq.html#locating-matplotlib-config-dir bir örnek olarak, http://code.google.com/apis/earth/documentation/releasenotes.html adresine). Ayrıca , sayfanın altında örnek bir yapılandırma dosyası olan matplotlib.org/users/customizing.html adresine bakın. Bu sayfada "agg" yi bulun ve ihtiyacınız olan yapılandırma seçeneğini göreceksiniz.
Reinout van Rees

4
Referans olarak, bunu açıklayan matplotlib belgelerine bağlantı . (+1, harika yanıt, bana mükemmel bir şekilde yardımcı oldu!)
Tim S.

72

Tıpkı Reinout'un cevabının bir tamamlayıcısı olarak.

Bu tür bir sorunu çözmenin kalıcı yolu .matplotlibrc dosyasını düzenlemektir. Aracılığıyla bulun

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

Ardından bu dosyadaki arka ucu olarak değiştirin backend : Agg. İşte bu.


5
Pro ipucu: set $MATPLOTLIBRCiçin dizindeki size kendi matplotlibrc atmak istiyorum.
Kenneth Hoste

Böyle bir sorun için biraz aşırı, ama sunucu her zaman başsız çalışıyor sanırım bir yapılandırma dosyasını değiştirmek mantıklı. Bunun matplotlib'in nasıl işleyeceği üzerinde herhangi bir yan etkisi olur mu?
BruceJohnJennerLawso

Bir web sunucusunda matplotlib çalıştırıyorum, bu yüzden bu benim için cevaptı. Herhangi bir yan etki fark etmedim.
spitz

42

Temiz cevap, yürütme ortamınızı doğru bir şekilde hazırlamak için biraz zaman ayırmaktır.

Eğer çalıştırma ortamını hazırlamak zorunda İlk teknik bir kullanmaktır matplotlibrcdosyayı olarak akıllıca Chris Q. tarafından önerilen ayar,

backend : Agg

bu dosyada. Matplotlib'in matplotlibrcdosyayı nasıl ve nerede arayacağını ve nerede bulacağını - kod değişikliği olmadan - bile kontrol edebilirsiniz .

Yürütme ortamınızı hazırlamanız gereken ikinci teknik, MPLBACKENDortam değişkenini kullanmaktır (ve kullanıcılarınızı bundan yararlanmaları için bilgilendirmektir):

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

Bu işe yarar, çünkü bu işi yapmak için diskte başka bir dosya bile sağlamanız gerekmez. Bu yaklaşımı, örneğin sürekli entegrasyonda test etme ve ekranları olmayan uzak makinelerde çalıştırma ile kullandım.

Matplotlib arka ucunuzu Python kodunuzda "Agg" ye sabit olarak kodlamak, kare bir peg'i büyük bir çekiçle yuvarlak bir deliğe daldırmaya benzer, bunun yerine matplotlib'e kare bir delik olması gerektiğini söylemiş olabilirsiniz.


İkinci teknik, bu durumda en zarif görünmektedir.
Dmitry Kabanov

MPLBACKEND kullanmak benim için çözdü. Kesinlikle en zarif yol!
SaturnFromTitan

41

Spark aracılığıyla matplotlib kullanırken hata aldım. matplotlib.use('Agg')benim için çalışmıyor. Sonunda, aşağıdaki kod benim için çalışıyor. Daha fazlası burada

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

Matplotlib ve diğer kütüphaneleri içe aktarmak için kullanılan siparişle ilgili kısıtlamalar olmaksızın bu harika çalışır.
PabTorre

Spark üzerinde çalışırken, bunu baş düğümde çalışacak şekilde sınırlamak zorunda kaldınız mı yoksa çalışan düğümlerde çalışırken bunu elde ettiniz mi?
Saca

Bunu bir django projesinde kullanıyorum ve çalıştırabilmemin tek yolu buydu.
HenryM

31

Sadece @Ivo Bosticky'nin gözden kaçabilecek söylediklerini tekrarlayacağım. Bu satırları py dosyasının ÇOK başlangıcına koyun .

import matplotlib
matplotlib.use('Agg') 

Ya da biri hata alır

* / usr / lib / pymodules / python2.7 / matplotlib / __ init__.py:923: UserWarning: matplotlib.use () öğesine yapılan bu çağrının hiçbir etkisi yoktur
çünkü arka uç zaten seçilmiş;
matplotlib.use (), * pylab, matplotlib.pyplot, * öncesinde * çağrılmalıdır.

Bu, tüm Ekran sorununu çözecektir


15

Bu snippet'in X ve X olmayan ortamlar arasında geçiş yaparken iyi çalıştığını gördüm.

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

Bence bu, doğrudan soruyu cevaplamasa da sorulmayan bir soruyu cevaplasa da, kabul edilenden üstün bir çözümdür.
Daisuke Aramaki

14

Kodu yürütmek için sunucuda oturum açarken bunun yerine şunu kullanın:

ssh -X username@servername

-XHiçbir görüntü adı ve hiçbir $ DISPLAY değişkeni hata kurtulur

:)


1
.Png görüntüsünün kaydedilmesi için '-X' kullanmam gerekiyor. Çok teşekkürler.
nos

Bu, ssh zaman aşımına uğradığında veya herhangi bir nedenle bağlantıyı kesmeniz gerektiğinde uzun bir işlem için başarısız olacaktır. Bağlanan istemci uyku durumuna geçse bile bir zaman aşımı gerçekleşebileceğini unutmayın.
posdef

-o ServerAliveCountMax=120 -o ServerAliveInterval=30Ssh istemcisinin en fazla 1 saat boyunca her 30 saniyede bir boş paket göndermesini sağlayacak zaman aşımlarını önleyebilirsiniz .
Alex

5

Hangi sistemdesiniz? X11 ile bir sisteminiz var gibi görünüyor, ancak DISPLAY ortam değişkeni düzgün ayarlanmamış. Aşağıdaki komutu çalıştırmayı ve ardından programınızı yeniden çalıştırmayı deneyin:

export DISPLAY=localhost:0

ama neden bir ekran değişkeni ayarlamak için eed yapar, uzaktan bu sunucuda oturum açtım, tek yapması gereken bir PNG dosyası oluşturmak ???
krisdigitx

1
@krisdigitx, uzaktan bağlıysanız, bir görüntüleme değişkeni ayarlamayın; bunun yerine bağlandığınızda "-XY" bayrağını kullanın. Görüntülemek için, görüntüyü hangi Xserver'a göndereceğini bilmek gerekir; bu durumda, uzak bilgisayar yerine bilgisayarınızın görüntüsü olacaktır. "-XY" bayrağını kullanmak SSH'nin DISPLAY değişkenini otomatik olarak bağlanan bilgisayarın ekranını gösterecek şekilde ayarlamasına neden olur.
Michael Aaron Safyan

@krisdigitx, katılıyorum, bunu yapmak çok garip; sanırım X11 kullanarak görüntüyü boyar ve X11 kullanarak sonucu kaydeder.
Michael Aaron Safyan

$ DISPLAY için bu ayarı kullanmak Ubuntu 16 çalıştıran
EC2'de çalışmaz

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

Benim için çalışıyor.


3

Kontrol edilmesi gereken bir diğer şey, mevcut kullanıcınızın X ekranına bağlanma yetkisine sahip olup olmadığıdır. Benim durumumda, root'un bunu yapmasına izin verilmedi ve matplotlib aynı hatayla şikayet ediyordu.

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

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


2

Kodunuzun Windows, Linux ve OSX'te ve ekranlı ve ekransız sistemlerde taşınabilir olduğundan emin olmak için aşağıdaki snippet'i öneririm:

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

Kredi bilgileri: https://stackoverflow.com/a/45756291/207661


1

Google Cloud Machine Öğrenim Motoru için:

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

Ve sonra dosyaya yazdırmak için:

#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 oluşturmak için:

multi_page(report_name)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.