El siguiente ejemplo muestra cómo se pueden comunicar threads a traves de cola y como se puede utilizar las características de las colas para hacer que un hilo solo trabaje cuando hay algo para hacer.
En el ejemplo se crean 2 clases:
Reader: se bloquea esperando un mensaje de una cola llamada self.in_queue, cuando hay algo lo imprime, si el mensaje es 'quit' saluda y finaliza
Writer: se bloquea esperando un mensaje de una cola llamada self.in_queue, cuando hay algo lo invierte y lo envia a la cola de salida (self.out_queue), si el mensaje es 'quit', lo pone en self.out_queue, saluda y finaliza.
En el ejemplo se crea un hilo Reader, un Writer, se inicializan ambos y se conecta la cola de salida de Writer con la entrada de Reader, de esta manera, cualquier mensaje enviado a la cola de entrada de Writer sera invertida, enviada por la salida, la cual sera leida por Reader e impresa, al introducir el mensaje 'quit' ambos threads finalizan.
import Queue import threading # este thread se bloquea esperando que venga algo en la cola, # lo unico que hace es imprimirlo. Si el mensaje es quit finaliza class Reader(threading.Thread): def __init__(self, in_queue): threading.Thread.__init__(self) self.in_queue = in_queue def run(self): while True: msg = self.in_queue.get() if msg == 'quit': print 'reader se va!' break print 'leido ' + msg # este thread se bloquea esperando que venga algo en la cola de entrada, # cuando llega algo lo escribe al reves en la cola de salida. class Writer(threading.Thread): def __init__(self, in_queue, out_queue): threading.Thread.__init__(self) self.in_queue = in_queue self.out_queue = out_queue def run(self): while True: msg = self.in_queue.get() if msg == 'quit': print 'writer se va!' self.out_queue.put(msg) break print 'escrito ' + msg self.out_queue.put(msg[::-1]) # aca creo un lector y un escritor, le doy de salida a writer la # entrada de reader, por lo tanto lo que escriba writer lo va a # leer reader al reves el recorrido es asi: # mensaje -> entra a writer -> lo invierte -> lo envia a la salida -> entra a reader def test(): in_queue = Queue.Queue() out_queue = Queue.Queue() reader = Reader(out_queue) writer = Writer(in_queue, out_queue) reader.start() writer.start() in_queue.put('buenas') in_queue.put('como va') in_queue.put('quit') if __name__ == '__main__': test()
En este ejemplo, los hilos están dormidos y solo se despiertan cuando hay algo que hacer, lo hacen y se vuelven a bloquear.
Usando esta estrategia nos queda el hilo principal libre para hacer lo que queramos (por ejemplo el main loop de un widget toolkit) el cual no se verá bloqueado por el trabajo realizado por los hilos.
Más info sobre el módulo Queue: https://docs.python.org/current/library/queue.html
Asynchronous Queue a partir de Python 3.4: https://docs.python.org/current/library/asyncio-queue.html
La salida obtenida ejecutando el archivo:
escrito buenas leido saneub escrito como va leido av omoc writer se va! reader se va!