Bienvenidos sean a este post, hoy veremos como son las comunicaciones en un thread.
Para este caso primero veremos como realizar las comunicaciones y despues como enviar eventos, comencemos con el primer caso a traves de un ejemplo, primero importemos los modulos necesarios:
>>> import threading
>>> from queue import Queue
Aqui la que nos interesa mas es Queue que sera la encargada de hacer la magia, lo siguiente sera crear un objeto:
>>> CENTINELA = object()
Este es un objeto simple que lo usaremos para que sirva como señal para indicar que pase de un thread a otro pero de esto hablaremos mas adelante, para nuestro siguiente paso definiremos una nueva funcion:
>>> def productor(e, n):
... a, b = 0, 1
... while a <= n:
... e.put(a)
... a, b = b, a + b
... e.put(CENTINELA)
...
>>>
Esta funcion recibe dos atributos, uno de tipo Queue y un valor, luego definiremos dos variables llamadas a y b, mientras a sea menor o igual a n hara un bucle con while y en este agregaremos al Queue el valor de a, lo siguiente es trabajar como hicimos con la funcion Fibo que vimos en este post, donde reemplazaremos el valor de a con b y el de b con la suma de ambos, por ultimo pasaremos a Queue el objeto CENTINELA el cual informara a la siguiente funcion que este esta preparado, pasemos a definir la siguiente funcion:
>>> def consumidor(e):
... while True:
... num = e.get()
... e.task_done()
... if num is CENTINELA:
... break
... print(f'Consegui el numero {num}')
...
>>>
Esta funcion recibe el objeto de Queue, mientras sea True ejecutara la misma, en num almacenaremos lo almacenado en el Queue informado, luego usaremos a task_done para verificar que todo ha sido procesado, lo siguiente es un condicional donde verifica si num es igual a CENTINELA y en caso de ser verdadero llama a break para salir del bucle lo siguiente sera mostrar el valor de num mientras corra el bucle, con esto tenemos las dos funciones definidas ahora vamos a implementarlas, lo siguiente sera crear el objeto para el Queue:
>>> e = Queue()
Lo siguiente sera crear los dos threads para nuestras funciones:
>>> cns = threading.Thread(target=consumidor, args=(e, ))
>>> prd = threading.Thread(target=productor, args=(e, 35))
Observen como pasamos el objeto creado para el Queue como argumento, en el caso del consumidor solamente el Queue y en el productor al Queue y el valor que servira de limite, lo siguiente sera iniciar ambos threads:
>>> cns.start()
>>> prd.start()
Cuando iniciemos nuestro thread del consumidor no sucedera nada pero esta esperando lo que genere la otra funcion, cuando iniciemos el productor sucedera lo siguiente:
Consegui el numero 0
Consegui el numero 1
Consegui el numero 1
Consegui el numero 2
Consegui el numero 3
Consegui el numero 5
Consegui el numero 8
Consegui el numero 13
Consegui el numero 21
Consegui el numero 34
>>>
Como pueden ver funciono hasta superar el valor de 35, por ultimo lo que debemos hacer es usar el join para liberar todos los elementos que hayan sido procesados:
>>> e.join()
Esta es una forma de poder pasar informacion entre dos threads, ahora vamos a pasar al siguiente tema.
Enviando eventos
Para este caso vamos a escribir otro ejemplo, comenzaremos importando solamente el modulo para los threads:
>>> import threading
Lo siguiente sera definir una funcion llamada inicio:
>>> def inicio():
... print('Iniciando evento...')
... evento.set()
...
>>>
Este es una funcion simple que mostrara un mensaje de inicio de un evento, y luego estableceremos el evento por medio de set, nuestros siguiente paso sera definir otra funcion:
>>> def escuchar():
... evento.wait()
... print('Evento ha sido iniciado')
...
>>>
Esta nueva funcion lo primero que hara sera esperar que el evento haya sido iniciado o establecido y despues mostrara un mensaje haciendo referencia a esto, nuestro siguiente paso sera crear el evento en si:
>>> evento = threading.Event()
Es simplemente crear el objeto que mencionamos antes con el metodo Event de threading, despues crearemos los dos threads para las funciones:
>>> t1 = threading.Thread(target=inicio)
>>> t2 = threading.Thread(target=escuchar)
Tan simple como hasta ahora donde cada target es una de las funciones antes definidas, nuestro siguiente paso sera iniciar el thread llamado t2:
>>> t2.start()
Este thread no hara nada porque esta esperando que evento sea establecido y como todavia no lo hicimos se quedara ahi cargado y esperando, el siguiente paso sera iniciar a t1:
>>> t1.start()
Y aqui si sucedera la magia, veamos la salida:
Iniciando evento...
>>> Evento ha sido iniciado
En este caso vemos la salida de la funcion inicio pero automaticamente se mostrara la funcion escuchar porque al iniciarse evento este puede seguir con sus instrucciones.
En resumen, hoy hemos visto como se comunican entre threads, hemos visto como lo hace a traves de un objeto que actua como señal, luego hemos visto como podemos utilizar eventos entre distintos threads para esperar que uno trabaje con el otro, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
