2011-05-31 22 views
6

Me he encontrado con este problema con show() una y otra vez, y estoy seguro de que estoy haciendo algo mal pero no estoy seguro de la forma "correcta" de hacer lo que quiero.(python) matplotlib pyplot show() .. bloqueando o no?

Y [creo] lo que quiero es una manera de bloquear en el hilo principal hasta que ocurre un evento en el hilo GUI, algo como esto funciona la primera vez:

from matplotlib import pyplot as p 
from scipy import rand 

im = (255*rand(480,640)).astype('uint8') 
fig = p.figure() 
ax = fig.add_subplot(111) 
ax.imshow(im) 

# just any mutable container for storing a click 
s = [-1, -1] 

def onclick(event): 
    if event.xdata is not None and event.ydata is not None: 
    s[0] = event.xdata 
    s[1] = event.ydata 
    p.close() 

cid = fig.canvas.mpl_connect('button_press_event', onclick) 
p.show() 
print s 

los p.show() bloques hasta p.close() se llama en el controlador de eventos. Pero cuando ejecuta el mismo código la segunda vez, pasa por el p.show() e imprime ese original s, [-1, -1].

He leído información contradictoria sobre si p.show() se puede o no llamar más de una vez desde el mismo programa. Parece que fue diseñado para usarse una vez, y solo una vez al final de una secuencia de comandos. Otros casos de uso parecen romper pyplot de alguna manera (¿máquina de estados?).

He tratado de utilizar combinaciones de p.draw() y p.ion() y p.ioff(), pero no pudo conseguir el comportamiento que quería (ya sea las cosas no estaban bloqueando correctamente o las parcelas no aparecían en el momento adecuado).

También estoy confundido acerca de cómo el controlador de eventos puede ver s aquí y si esta es una forma pobre de pasar la información de entrada/salida. Si no utilizo un contenedor mutable como una matriz o lista, la información que quiero establecer por el controlador de eventos simplemente se pierde como una variable local. ¿Hay algún otro método que me esté perdiendo, donde el hilo de la GUI puede pasar las señales al hilo principal? ¿Hay alguna manera de bloquear en main, sin un sondeo periódico o una espera ocupada, una señal del controlador de eventos antes de continuar?

así que supongo que en última instancia, mi pregunta principal es:

¿Hay un reemplazo aseado para p.show(), que hace lo que yo quiero (el mismo comportamiento que p.show() tiene la primera vez), o hace este tipo de código requiere una completar repensar/reescribir?

Respuesta

1

que era capaz de resolver mi problema hoy en día. si alguien está interesado en cambiar el comportamiento de show(), para leer en cómo puede hacerlo:

me di cuenta de este párrafo titulado varias llamadas para mostrar el apoyo por parte what's new de la página web matplotlib:

Una solicitud de larga duración es para admitir llamadas múltiples a show(). Esto ha sido difícil porque es difícil obtener un comportamiento consistente a través de los sistemas operativos, los kits de herramientas de interfaz de usuario y las versiones.Eric Firing ha trabajado mucho para racionalizar el show en backends, con el comportamiento deseado para hacer que Show muestre todas las figuras recién creadas y bloquee la ejecución hasta que se cierren. Las llamadas repetidas para mostrar deben aumentar las cifras recién creadas desde la última llamada. Eric ha realizado muchas pruebas en los kits de herramientas de la interfaz de usuario, las versiones y las plataformas a las que tiene acceso, pero no es posible probarlas todas, así que informe los problemas a la lista de correo y al rastreador de errores.

Esto fue en 'lo nuevo' para la versión 1.0.1, al momento de escribir la versión en sináptica es todavía nuevo en 0.99.3. Pude descargar y compilar desde la fuente v1.0.1. Paquetes adicionales que también requerí para satisfacer dependencias fueron libfreetype6-dev tk-dev tk8.5-dev tcl8.5-dev python-gtk2-dev.

Ahora con matplotlib.__version__ == 1.0.1, los siguientes bloques de código como me esperarían:

import matplotlib.pyplot as p 
from scipy import eye 
p.imshow(eye(3)) 
p.show() 
print 'a' 
p.imshow(eye(6)) 
p.show() 
print 'b' 
p.imshow(eye(9)) 
p.show() 
print 'c' 
2

Ideas par de calidad variable:

Si no te gusta s siendo una variable global, que podría hacer onclick() de un objeto invocable adjuntarlo a eso.

Su devolución de llamada podría adquirir/liberar un bloqueo para controlar el flujo del programa (poco sucio).

Puede sondear activamente para controlar el flujo del programa (muy sucio).

Se puede controlar manualmente el dibujo de sus cifras a través de fig.canvas.draw()

+0

gracias por sus ideas. Pude cambiar el comportamiento de bloqueo de show() creando mpl desde source. – wim

0

me di cuenta de una diferencia entre ejecutar el código

  1. directamente dentro del intérprete de Python (línea de comandos)

  2. Poniéndolo en un script de Python y ejecutándolo desde la línea de comando ("python script.py")

Ambos dan un comportamiento de bloqueo, lo cual está bien.

Desde el intérprete aparecen ambas imágenes, desde la línea de comandos solo aparece la primera.

Cuestiones relacionadas