2015-03-23 12 views
8

Quando si esegue un codice che utilizza la libreria matplotlib nel mio PC desktop, non ho problemi con la linea:

import matplotlib.pyplot as plt 

in basso il codice, che è dove ho effettivamente utilizzare le funzioni stampa.

se corro il codice in un server anche se funziona solo se importare matplotlibprima, e costringerlo a utilizzare il Agg backend. Vale a dire, devo aggiungere le seguenti righe all'inizio del codice:

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

(vedere this answer in cui questo è spiegato). Altrimenti il ​​codice si bloccherà con TclError: no display name and no $DISPLAY environment variable (vedere this question per esempio).

La domanda è: perché devo fare questo? La soluzione funziona perfettamente, ma non so perché non devo farlo nel mio PC desktop, ma devo assolutamente farlo quando il codice viene eseguito nel server.

+0

è sempre possibile impostare $ DISPLAY Esporta DISPLAY =: 0' Penso che ... –

+0

Non sto davvero cercando un altro modo per risolvere questo problema perché quello attuale funziona perfettamente. Quello che voglio è _understand_ perché funziona. Non capisco veramente la soluzione alternativa nel tuo cmmt o BTW :) – Gabriel

+2

'DISPLAY' è usato dal sistema X-Windows su UNIX/Linux, non è colpa di matplotlib o Python, proprio come stanno le cose piattaforma. Il motivo è la flessibilità, è possibile selezionare diversi display in base alla variabile di ambiente. – cdarke

risposta

9

X11 segue un modello client/server, in cui il server X accetta richieste di output grafico da applicazioni client (es. , le applicazioni client devono sapere a quale server X inviare le loro richieste. Questo è controllato dalla variabile di ambiente $DISPLAY. Nel caso in cui ci si connetta a una sessione X remota (ad esempio tramite una connessione SSH), la variabile $DISPLAY nella sessione remota deve puntare al proprio server X locale.

La variabile $DISPLAY è strutturata:

hostname:displaynumber.screennumber 

Non tutti i dettagli possono essere presenti - il nome host è solitamente omesso per sessioni locali, e il numero di pagina viene omesso anche se v'è un solo schermo. In una sessione di terminale locale sul computer portatile, il mio $DISPLAY assomiglia a questo:

[email protected]:~$ echo $DISPLAY 
:0 

A condizione che il server remoto supporta anche X11, è possibile aprire le finestre grafiche sulla macchina remota e li hanno visualizzati sul computer locale utilizzando X11 forwarding . Per una connessione SSH, fai questo passando il flag -X (o -Y).

Ad esempio:

[email protected]:~$ ssh -X [email protected] 
[email protected]:~$ echo $DISPLAY 
localhost:10.0 

Il server SSH remoto dovrebbe prendersi cura di impostare la variabile $DISPLAY in modo appropriato quando si apre la connessione. In questo caso particolare, localhost:10.0 è in realtà un server X11 "proxy" in esecuzione sul computer remoto che ascolta 10 e invia i comandi al server X locale tramite la connessione SSH (take a look at this se si è interessati ai dettagli).

Ora dovresti essere in grado di avviare una sessione IPython remota, importare matplotlib usando un backend interattivo e creare finestre di trama che appariranno sul tuo computer locale. Poiché l'input da tastiera/mouse e l'output del display passano ora su una connessione di rete crittografata, le finestre di trama saranno meno reattive di quelle a cui sei abituato per una sessione locale.

Un altro avvertimento: se si ha una sessione IPython aperta con una sessione matplotlib interattiva in esecuzione è impossibile chiudere la connessione SSH senza uccidere il processo IPython. A volte chiamo anche matplotlib.use("Agg") prima di iniziare un processo di lunga durata che importa matplotlib - in questo modo posso disconnettermi dal server remoto senza uccidere il processo.

Problemi correlati