Detección automática de disponibilidad de pantalla con matplotlib.

Estoy generando cifras de matplotlib en un script que ejecuto alternativamente con o sin una pantalla gráfica. Me gustaría que la secuencia de comandos se ajuste automáticamente: con la pantalla, debería mostrar las figuras de manera interactiva, mientras que sin una pantalla, debería guardarlas en un archivo.

De una respuesta a la pregunta Generando gráficos de matplotlib sin un servidor X en ejecución , aprendí que se puede usar el backend de Agg para trazados no interactivos.

Así que estoy intentando con este código:

import matplotlib try: import matplotlib.pyplot as plt fig = plt.figure() havedisplay = True except: matplotlib.use("Agg") import matplotlib.pyplot as plt fig = plt.figure() havedisplay = False # do the plotting if havedisplay: plt.show() else: fig.savefig("myfig.png") 

Esto funciona como excepción en el caso con una pantalla. Sin embargo, sin una pantalla, la llamada a matplotlib.use no es efectiva, ya que la pantalla ya ha sido elegida. Está claro que debo llamar a matplotlib.use antes de import matplotlib.pyplot , pero no sé cómo probar si hay una pantalla disponible o no.

También he intentado con la función experimental matplotlib.switch_backend lugar de matplotlib.use , pero esto genera un RuntimeError.

¿Alguien tiene una idea de cómo hacer que el código anterior funcione según lo previsto, o puede sugerir una forma alternativa de detectar si una pantalla está disponible para matplotlib o no?

Puede detectar directamente si tiene una pantalla con el módulo del sistema operativo en python. en mi caso es

 >>> import os >>> os.environ["DISPLAY"] ':0.0' 

¿prueba esto?

 import matplotlib,os r = os.system('python -c "import matplotlib.pyplot as plt;plt.figure()"') if r != 0: matplotlib.use('Agg') import matplotlib.pyplot as plt fig = plt.figure() fig.savefig('myfig.png') else: import matplotlib.pyplot as plt fig = plt.figure() plt.show() 

El código a continuación funciona para mí en Linux y Windows (si se supone que hay un dispositivo de visualización):

 import os import matplotlib if os.name == 'posix' and "DISPLAY" not in os.environ: matplotlib.use('Agg') 

Consulte https://stackoverflow.com/a/1325587/896111 .

Tenga en cuenta que la línea matplotlib.use('Agg') debe aparecer después de la primera importación de matplotlib (de lo contrario obtendrá un error).

Al combinar los dos enfoques anteriores, quizás obtenga la mejor solución:

 havedisplay = "DISPLAY" in os.environ if not havedisplay: exitval = os.system('python -c "import matplotlib.pyplot as plt; plt.figure()"') havedisplay = (exitval == 0) 

El motivo de este combo es que el tiempo de os.system comando os.system puede tardar un tiempo. Entonces, cuando esté seguro de tener la pantalla (a juzgar por el valor de os.environ ), puede ahorrar ese tiempo. Por otro lado, incluso si la tecla DISPLAY no está configurada en la variable os.environ , todavía existe la posibilidad de que los métodos de trazado funcionen con la interfaz gráfica (por ejemplo, cuando se usa la línea de comandos de Windows).

cuando use el backend GUI, el objeto figura tiene el método show (), puede usarlo para hacer el cambio:

 import matplotlib #matplotlib.use("Agg") import matplotlib.pyplot as plt fig = plt.figure() havedisplay = False if hasattr(fig, "show"): plt.show() else: print "save fig" fig.savefig("myfig.png") 

La solución ofrecida por @ Oz123 generó un error de syntax para mí. Sin embargo, pude detectar fácilmente la pantalla usando:

 import os havedisplay = "DISPLAY" in os.environ #plotting... 

Eso fue lo más simple que pude encontrar, de todos modos.

 import os have_display = bool(os.environ.get('DISPLAY', None)) 

have_display es False si DISPLAY no está en el entorno o es una cadena vacía. de lo contrario, es verdad