Notas de Python: corrutinas y multiproceso

from multiprocessing import Pool, cpu_count
import time

urls = [1,2,3,4,5,6,7,8]
auth = 'auth'

def process_url(url, auth):
    time.sleep(9)
    print(url, auth)

if __name__ == '__main__':  # Necesario para evitar la creación recursiva de subprocesos
    with Pool(processes=max(1, cpu_count() - 1)) as pool:
        pool.starmap(process_url, [(url, auth) for url in urls])

1. yield

import time

def task1():
    while True:
        print("-----1-----")
        yield  # suspende la función y devuelve el control al llamante
        time.sleep(1)

def task2():
    while True:
        print("-----2-----")
        yield
        time.sleep(1)

gen1 = task1()
gen2 = task2()

while True:
    next(gen1)
    next(gen2)

yield es una palabra clave similar a return, con la diferencia de que return finaliza la ejecución de la función, mientras que yield permite reanudar la función desde la siguiente sentencia usando send() o next(). La función send() acepta un parámetro, send(param), que se envía al generador como resultado de la expresión yield. next(), en cambio, no envía ningún parámetro al generdaor.

2. greenlet

import time
import greenlet

def tarea1():
    while True:
        print("----1----")
        g2.switch()  # cambia a tarea2
        time.sleep(1)

def tarea2():
    while True:
        print("----2----")
        g1.switch()  # cambia a tarea1
        time.sleep(1)

g1 = greenlet.greenlet(tarea1)
g2 = greenlet.greenlet(tarea2)
g1.switch()

greenlet no es un mecanismo de concurrencia real, sino una alternancia entre distitnos bloques de código de funciones dentro del mismo hilo. Cuando aparece un bloqueo, se conmuta explícitamente hacia el segmento de código que no está bloqueado; este segmento no continuará hasta que otro segmento vuelva a conmutar hacia él.

3. gevent

import gevent
import time

def tarea1():
    while True:
        print("----1----")
        gevent.sleep(1)  # sleep no bloquea el hilo

def tarea2():
    while True:
        print("----2----")
        gevent.sleep(1)

# Crea e inicia las corrutinas
g1 = gevent.spawn(tarea1)
g2 = gevent.spawn(tarea2)
# Espera a que todas terminen
gevent.joinall([g1, g2])

gevent se basa en greenlet y utiliza el mecanismo epoll para lograr la conmutación automática de hilos, garantizando que siempre haya un greenlet en ejecución en lugar de esperar por E/S. El método gevent.spawn() crea y ejecuta un nuevo objeto de corrutina greenlet. El método gevent.joinall() acepta una lista de objetos de corurtina y espera a que todos hayan terminado antes de salir.

Etiquetas: Python Corrutinas multiprocessing Yield greenlet

Publicado el 9-7 08:07