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.