336 Stimmen

Generierung einer PNG mit matplotlib, wenn DISPLAY nicht definiert ist

Ich versuche, networkx mit Python zu verwenden. Wenn ich dieses Programm ausführe, erhalte ich diesen Fehler. Fehlt etwas?

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

Jetzt erhalte ich einen anderen Fehler:

#!/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:  Dieser Aufruf von matplotlib.use() hat keine Auswirkung,
weil das Backend bereits ausgewählt wurde;
matplotlib.use() muss *vor* pylab, matplotlib.pyplot
oder matplotlib.backends importiert werden, bevor es zum ersten Mal verwendet wird.

  if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
  File "graph.py", line 15, in 
    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

Jetzt erhalte ich einen anderen Fehler:

#!/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:  Dieser Aufruf von matplotlib.use() hat keine Auswirkung,
weil das Backend bereits ausgewählt wurde;
matplotlib.use() muss *vor* pylab, matplotlib.pyplot
oder matplotlib.backends importiert werden, bevor es zum ersten Mal verwendet wird.

  if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
  File "graph.py", line 15, in 
    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

3 Stimmen

9 Stimmen

Verschieben Sie den Aufruf von matplotlib.use('Agg') über Ihre anderen Imports, insbesondere sollte er vor dem Import von matplotlib.pyplot stehen.

0 Stimmen

@IvoBosticky Kommentar hat es auch für mich gelöst: Das einzige, was irreführend ist, ist "über Ihren anderen Imports". Es sollte offensichtlich sein, dass Sie matplotlib importieren müssen, bevor... Dies ist die gesamte Einstellung, die für mich funktioniert hat:
importiere matplotlib // matplotlib.use('Agg') // importiere matplotlib.pyplot as plt

534voto

Reinout van Rees Punkte 13168

Das Hauptproblem ist, dass (auf Ihrem System) matplotlib standardmäßig ein x-verwendendes Backend auswählt. Ich hatte gerade dasselbe Problem auf einem meiner Server. Die Lösung für mich bestand darin, den folgenden Code an einer Stelle hinzuzufügen, die vor jedem anderen pylab/matplotlib/pyplot-Import gelesen wird:

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

Die Alternative besteht darin, es in Ihrer .matplotlibrc zu setzen

191 Stimmen

Wichtiger Hinweis: .use muss aufgerufen werden, bevor pyplot importiert wird. Wenn Sie beispielsweise versuchen, nur pyplot zu importieren, müssen Sie zuerst matplotlib importieren, .use aufrufen und dann pyplot importieren.

9 Stimmen

Der obige Kommentar wird in dieser Antwort näher erläutert.

2 Stimmen

Wie setzt man es in Ihrer .matplotlibrc?

74voto

Chris.Q Punkte 1310

Genau wie als Ergänzung zu Reinouts Antwort.

Der dauerhafte Weg, um diese Art von Problem zu lösen, besteht darin, die Datei .matplotlibrc zu bearbeiten. Finden Sie sie über

>>> import matplotlib>>> matplotlib.matplotlib_fname()
# Dies ist der Dateispeicherort in Ubuntu
'/etc/matplotlibrc'

Dann ändern Sie das Backend in dieser Datei in backend : Agg. Das ist es.

5 Stimmen

Profi-Tipp: Setze $MATPLOTLIBRC auf das Verzeichnis, in dem du deine eigene matplotlibrc ablegen möchtest.

0 Stimmen

Ziemlich übertrieben für ein Problem wie dieses, aber ich denke, wenn der Server immer ohne Benutzeroberfläche funktioniert, macht es Sinn, eine Konfigurationsdatei zu ändern. Hätte dies Auswirkungen darauf, wie matplotlib funktioniert?

0 Stimmen

Ich führe matplotlib auf einem Webserver aus, daher war dies die Antwort für mich. Ich habe keine Nebenwirkungen bemerkt.

46voto

gotgenes Punkte 36305

Die saubere Antwort ist, sich ein wenig Zeit zu nehmen, um Ihre Ausführungsumgebung korrekt vorzubereiten.

Die erste Technik, um Ihre Ausführungsumgebung vorzubereiten, besteht darin, eine matplotlibrc-Datei zu verwenden, wie von Chris Q. weise empfohlen, und

backend : Agg

in dieser Datei festzulegen. Sie können sogar steuern — ohne Änderungen am Code — wie und wo matplotlib nach der matplotlibrc-Datei sucht und sie findet.

Die zweite Technik, um Ihre Ausführungsumgebung vorzubereiten, besteht darin, die MPLBACKEND-Umgebungsvariable zu verwenden (und Ihre Benutzer darauf hinzuweisen, diese zu nutzen):

export MPLBACKEND="agg"
python 

Dies ist praktisch, da Sie noch nicht einmal eine weitere Datei auf der Festplatte bereitstellen müssen, um dies zu erreichen. Ich habe diesen Ansatz bereits bei Tests in der kontinuierlichen Integration und beim Ausführen auf entfernten Maschinen ohne Bildschirme verwendet.

Ihr Matplotlib-Backend in Ihrem Python-Code hart zu kodieren, um "Agg" zu sein, ist wie mit einem großen Hammer ein quadratisches Stück in ein rundes Loch zu schlagen, wenn Sie stattdessen einfach matplotlib mitteilen könnten, dass es ein quadratisches Loch sein muss.

0 Stimmen

Die zweite Technik sieht in dieser Situation am elegantesten aus.

0 Stimmen

Durch die Verwendung von MPLBACKEND wurde das Problem für mich gelöst. Definitiv der eleganteste Weg!

44voto

user3282611 Punkte 810

Ich habe den Fehler bekommen, als ich matplotlib durch Spark verwendet habe. matplotlib.use('Agg') funktioniert nicht für mich. Am Ende funktioniert der folgende Code für mich. Mehr hier

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

0 Stimmen

Dies funktioniert hervorragend, ohne die Beschränkungen hinsichtlich der Reihenfolge, in der matplotlib und andere Bibliotheken importiert werden.

0 Stimmen

Beim Ausführen auf Spark musstest du dies auf dem Kopf- oder Arbeitsknoten einschränken oder konntest du dies zum Laufen bringen, wenn du auf Worker-Knoten ausgeführt hast?

0 Stimmen

Ich verwende dies in einem Django-Projekt und das war der einzige Weg, wie ich es zum Laufen bringen konnte.

31voto

Somum Punkte 2162

Ich werde nur wiederholen, was @Ivo Bosticky gesagt hat, was übersehen werden kann. Setzen Sie diese Zeilen ganz am ANFANG der py-Datei.

import matplotlib
matplotlib.use('Agg') 

Oder man würde einen Fehler erhalten

\*/usr/lib/pymodules/python2.7/matplotlib/\_\_init\_\_.py:923: UserWarning:  Dieser Aufruf von matplotlib.use() hat keine Auswirkung,
weil das Backend bereits ausgewählt wurde;
matplotlib.use() muss \*vor\* pylab, matplotlib.pyplot aufgerufen werden.\*

Dies löst alle Anzeigeprobleme.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X