web-dev-qa-db-fra.com

Générer un fichier PNG avec matplotlib lorsque DISPLAY n'est pas défini

J'essaie d'utiliser networkx avec Python. Quand j'exécute ce programme, il obtient cette erreur. Est-ce qu'il manque quelque chose?

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

Je reçois une erreur différente maintenant:

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

Je reçois une erreur différente maintenant:

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

Le problème principal est que matplotlib (sur votre système) choisit par défaut un backend utilisant x. Je viens d'avoir le même problème sur l'un de mes serveurs. La solution pour moi a été d’ajouter le code suivant à un endroit lisible avant tout autre pylab/matplotlib/pyplot import :

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

L'alternative est de le définir dans votre .matplotlibrc

506
Reinout van Rees

Juste comme complément de la réponse de Reinout.

La façon permanente de résoudre ce genre de problème est d’éditer le fichier .matplotlibrc. Trouvez-le via

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

Puis modifiez le fichier dans ce fichier en backend : Agg. C'est ça.

71
Chris.Q

La réponse claire consiste à prendre un peu de temps pour préparer correctement votre environnement d'exécution.

La première technique que vous devez préparer votre environnement d’exécution consiste à utiliser un fichier matplotlibrc, , comme le recommande sagement Chris Q. , paramètre

backend : Agg

dans ce fichier. Vous pouvez même contrôler - sans changement de code - comment et où matplotlib cherche et trouve le fichier matplotlibrc .

La deuxième technique que vous devez préparer votre environnement d’exécution consiste à utiliser la variable d’environnement MPLBACKEND (et d’informer vos utilisateurs de l’utiliser):

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

C'est pratique car vous n'avez même pas besoin de fournir un autre fichier sur le disque pour que cela fonctionne. J'ai utilisé cette approche avec, par exemple, des tests d'intégration continue et une exécution sur des machines distantes sans affichage.

Coder en dur votre arrière-plan matplotlib en "Agg" dans votre code Python revient à frapper un piquet carré dans un trou rond avec un gros marteau, alors que vous auriez pu simplement dire à matplotlib que cela doit être trou carré.

42
gotgenes

J'ai eu l'erreur en utilisant matplotlib via Spark. matplotlib.use('Agg') ne fonctionne pas pour moi. En fin de compte, le code suivant fonctionne pour moi. Plus ici

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

Je vais simplement répéter ce que @Ivo Bosticky a dit et qui peut être négligé. Mettez ces lignes au début VERY du fichier py.

import matplotlib
matplotlib.use('Agg') 

Ou on aurait une erreur

 */usr/lib/pymodules/python2.7/matplotlib/__ init__.py:923: UserWarning: cet appel à matplotlib.use () n'a aucun effet 
 car le backend a déjà été 
 matplotlib.use () doit être appelé * avant * pylab, matplotlib.pyplot, * 

Cela résoudra tous les problèmes d'affichage

31
Somum

Lorsque vous vous connectez au serveur pour exécuter le code, utilisez plutôt ceci:

ssh -X username@servername

le -X supprime les erreurs de nom d'environnement no display et no $ DISPLAY

:)

14
rajol kochlashvili

J'ai trouvé que cet extrait fonctionnait correctement lors de la commutation entre des environnements X et non-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
13
Matthias123

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

Ça marche pour moi.

5
Qing En

Vous êtes sur quel système? Il semble que vous ayez un système avec X11, mais la variable d’environnement DISPLAY n’a pas été définie correctement. Essayez d’exécuter la commande suivante puis de réexécuter votre programme:

export DISPLAY=localhost:0
5

Une autre chose à vérifier est de savoir si votre utilisateur actuel est autorisé à se connecter à l’affichage X. Dans mon cas, root n'était pas autorisé à le faire et matplotlib se plaignait de la même erreur.

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

la source: http://www.debian-administration.org/articles/494 https://debian-administration.org/article/494/Getting_X11_forwarding_through_ssh_working_after_running_s

3
Alex

Pour vous assurer que votre code est portable sous Windows, Linux et OSX et pour les systèmes avec et sans écrans, je vous suggère de suivre l'extrait suivant:

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

Crédit: https://stackoverflow.com/a/45756291/207661

2
Shital Shah

Pour Google Cloud Machine Learning Engine:

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

Et puis imprimer dans un fichier:

#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()

et pour créer le PDF:

multi_page(report_name)
1
Kim Miller