0% encontró este documento útil (0 votos)
301 vistas24 páginas

Guia Asyncio

Parte de la colección de capítulos del Curso de Programación para Organizaciones Sociales, en castellano. Uso de Async io, característica que permite el trabajo asincrónico del software https://gitlab.com/pineiden/curso_programacion Consultas al grupo telegram: https://t.me/joinchat/F5CQ4RA6TM9AEc1qIxdpZw

Cargado por

pineiden
Derechos de autor
© Attribution Non-Commercial ShareAlike (BY-NC-SA)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
301 vistas24 páginas

Guia Asyncio

Parte de la colección de capítulos del Curso de Programación para Organizaciones Sociales, en castellano. Uso de Async io, característica que permite el trabajo asincrónico del software https://gitlab.com/pineiden/curso_programacion Consultas al grupo telegram: https://t.me/joinchat/F5CQ4RA6TM9AEc1qIxdpZw

Cargado por

pineiden
Derechos de autor
© Attribution Non-Commercial ShareAlike (BY-NC-SA)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 24

Concurrencia con Asyncio

David Pineda Osorio

November 20, 2018

Contents
1 Introducción 1

2 Síntaxis de asyncio 3
2.1 ¿Cómo utilizar una función asíncrona? . . . . . . . . . . . . . 5
2.1.1 El modo simple. . . . . . . . . . . . . . . . . . . . . . 6
2.1.2 Modo detallado. . . . . . . . . . . . . . . . . . . . . . 6
2.2 Ejecutar varias corrutinas dentro de un mismo loop . . . . . . 7
2.2.1 Llamar una corrutina dentro de otra . . . . . . . . . . 7
2.2.2 Llamar varias corrutinas asignadas a un loop . . . . . 8
2.2.3 Múltiples tareas con llamadas a await internamente. . 9

3 Un async while artesanal 11

4 Clase con métodos asíncronos 17


4.1 Ejecución en un proceso. . . . . . . . . . . . . . . . . . . . . . 22
4.2 Ejecución en múltiples procesos. . . . . . . . . . . . . . . . . . 22

5 Proyectos de Interés 23

6 Conocimiento recomendado 24

1 Introducción
Dentro de todos los distintos módulos de Python, el llamado asyncio (Doc-
umentación) por Asynchronous I/O (entrada/salida asincrónica) parece
ser uno de aquellos que abre todo un abanico de posibilidades ya que per-
mite un uso intensivo de los recursos del computador.

1
Permite acercarnos a la realidad de los eventos que ocurren en el contexto
operacional de estas tecnologías. Entrega un punto de conexión a aquellos
factores que no podemos controlar con nuestro programa pero que si necesi-
tamos acceder a estos. Por eso es que cambia el panorama o el paradigma
de desarrollo usual de un programa tradicional y la dificultad se torna expo-
nencial :(.
Pero todo tiene solución. La fortuna de que tenemos con python es que
provee las herramientas necesarias para poder crear valiosos trozos de código
que operan de manera asíncrona, y esta guia será la que te introducirá en
los principales conceptos a considerar para el uso de este módulo y creación
de asombroso código.
Si sucede que necesitamos acceder a una serie de eventos que no sabemos
cuando ocurren, pero que cuando ocurran debemos capturar esa información
y procesarla, entonces es recomendable implementar el software con asyncio.
Esto nos permitirá gestionar de mejor manera a que si tuvieramos una pila
de eventos a revisar secuencialmente, unos ocurrirían antes que otros, pero
para atender el que primero ocurra deberemos atender al que se active en el
orden correspondiente.
Para aclarar, cuando estamos atendiendo una serie de eventos de manera
secuencial. Sean estos respuesta desde una base de datos, información que
envían fuentes de datos o sensores, posteos de multiples personas, si los
vamos capturando de manera secuencial tendremos lo siguiente.

Esto implica en que habrá momentos ociosos del computador en que no

2
hará nada, el tiempo en que se atienda un evento será mayor y, por último,
será en conjunto menos eficiente.
De otra manera, cuando atendemos una serie de eventos, asignadas me-
diante tareas. Los mismos eventos del gráfico anterior se pueden ver de la
manera siguiente:

Podemos observar que, siendo un solo trabajador (procesador) atendi-


endo las mismas tareas, se hace mucho más eficaz. Ya que cada tarea una
vez que sucede y se libera de trabajo el procesador, procede a ejecutarse.
De eso se trata asyncio, una herramienta que puede ser un poco más
difícil de utilizar, nos entrega mejores prestaciones en la realización de tareas
múltiples.
El siguiente contenido consistirá en conocer la síntaxis de asyncio, los el-
ementos sean funciones y clases, el flujo de trabajo y ejemplos. Por último se
implementará una funcionalidad que vendría a ser un loop while asincrónico
con las herramientas que provee.

2 Síntaxis de asyncio
Python provee una serie de tipos de funciones que se caracterizan por como
entregan su resultado.

función tradicional

3
Es aquella clásica, que tiene una entrada y retorna algo (o solo hace algo),
ejecutada de manera secuencial.

def imprimir(msg):
print(msg)

def suma(a,b):
return a+b

función generador

Es una función especial que se encarga de generar cada nuevo valor a


medida que se solicita. Por ejemplo, series de número o valores, colecciones
de datos desde una base de datos, etc. Los generadores se activan con el uso
de yield, en que el interprete entrega un objeto generador

def gen_double(inicial, final, paso):


value = inicial
while value<final:
yield value+paso

Los/as desarrolladores del lenguaje definieron los documentos PEP que


determinan la síntaxis del uso de asyncio. Luego de esto, desde la versión
3.4 de python, es que es posible utilizar de manera sencilla la característica.
Es recomendable darle una mirada a los siguientes PEP:

PEP 492 https://www.python.org/dev/peps/pep-0492/

PEP 3156 https://www.python.org/dev/peps/pep-3156/

PEP 3153 https://www.python.org/dev/peps/pep-3153/

PEP 525 https://www.python.org/dev/peps/pep-0525/

PEP 492 https://www.python.org/dev/peps/pep-0492/

PEP 530 https://www.python.org/dev/peps/pep-0530/

En resumen, para crear una corrutina (la función de tipo asíncrona, el


nuevo tipo de funciones) se debe utilizar el par (async, await)

async para definir funciones corrutinas

4
await para usar corrutinas dentro de currutinas

De la misma manera que se programa cualquier función en un archivo


python, se realiza de la manera siguiente.

import asyncio

async def holacoro():


for i in range(3):
await asyncio.sleep(1)
print("Hola %d" % i)

Esta función asíncrona hace lo siguiente:

• Comienza la ejecución
• Espera un segundo (libera el procesador en tanto)
• Imprimir "Hola #numero"
• Lo hace tres veces.

2.1 ¿Cómo utilizar una función asíncrona?


Await one moment, no es tan simple. Llamar una corrutina requiere un
mayor protocolo o formalidad para poder ejecutarla. No es tan simple como
llamar una función. Son en cierto modo, unas funciones princesas.
¡Pero vamos! No son inalcanzables. El secreto es darle el toque perfecto.
No hay solo un camino, dentro de estas formalidades está el modo sencillo
de llamarlo hasta aquel modo en que queda muy claro cada paso.
Para eso debemos conocer los elementos de asyncio

loop es, por decir de alguna manera, el contexto o universo dentro del cual
se hace posible ejecutar las corrutinas. Como su nombre lo indica, y la
implementación, una máquina que realiza una serie de procedimientos
repetidamente que habilita las funcionalidades asíncronas.
corrutinas son las funciones asíncronas enunciadas, dentro de cuales se eje-
cuta código de manera secuencial. Estas se ejecutas solamente cuando
están dentro de un loop.
Futures Son un conjunto de funciones y objetos que proveen conectividad
entre la ejecución del loop a bajo nivel y las llamadas a las funciones
asíncronas en alto nivel.

5
Task Es una clase objecto que permite asignar la ejecución de una corrutina.
Está implementada como un objeto que hereda de Futures, esto quiere
decir que todas las funcionalidades habilitadas para esta clase padre o
madre, también están disponibles para Task.

2.1.1 El modo simple.


Ya tenemos la corrutina llamada holacoro, ahora procederemos a ejecutarla.
Se debe obtener el event loop, por defecto está el de asyncio. Aunque,
al estar pensado de manera modular, es posible utilizar otras implementa-
ciones de event loop como {quamash, uvloop, otras}.

import asyncio
from corrutinas import holacoro

# Obtener el loop asyncio


loop = asyncio.get_event_loop()

# Ejecutar la corrutina en el loop


loop.run_until_complete(holacoro())

# Cerrar el loop
loop.close()

Funciona, sí, pero no estamos viendo paso a paso la transformación que


sucede cuando necesitamos correr la función asíncrona.

2.1.2 Modo detallado.


En detalle, una función asíncrona debe ser enunciada, transformándose en
una corrutina que debe ser agendada como tarea o Task a futuro, cuando
el loop entre en ejecución.

import asyncio
from corrutinas import holacoro

# Obtener el loop asyncio


loop = asyncio.get_event_loop()

6
# Quiero ejecutar holacoro
# Debo crear una tarea
# Asignarla al "trabajador(procesador)"
# Encargado del loop

# Reviso si la funcion es corrutina

task = None
if asyncio.iscoroutinefunction(holacoro):
print("holacoro es corrutina, se crea tarea")
# se crea la corrutina
print("¿Qué es la función holacoro?")
print(holacoro)
coro = holacoro()
# se agenda para el loop
print("¿Qué es coro?")
print(coro)
task = asyncio.ensure_future(coro)
else:
print("holacoro no es corrutina, no se asigna")

if task:
loop.run_until_complete(task)

loop.close()

2.2 Ejecutar varias corrutinas dentro de un mismo loop


Al principio de la sesión vimos cómo era posible que en modo asincrónico
varias tareas podían ser atendidas. Hasta el momento solo hemos conocido
la forma general de operar con el módulo asyncio. Este módulo también
posibilita la ejecución de un conjunto de corrutinas asignadas a un mismo
loop.

2.2.1 Llamar una corrutina dentro de otra


Del mismo modo como una función puede ser llamada dentro de otra, una
función asíncrona (A) puede ser llamada o ejecutada dentro de una corrutina
(que es cuando es cuando una función asíncrona B se enuncia (B’ es la
corrutina)). Es bastante sencillo y aquí se utiliza la orden await.

7
from datetime import datetime
import asyncio

async def ahora_fecha():


return datetime.utcnow()

async def imprimir():


for i in range(3):
ahora = await ahora_fecha()
print("La fecha es %s" %ahora)
await asyncio.sleep(1)

loop = asyncio.get_event_loop()

loop.run_until_complete(imprimir())

loop.close()

2.2.2 Llamar varias corrutinas asignadas a un loop


Cuando necesitamos definir un grupo de tareas asignadas a un trabajador
(loop), será necesario que cada una de estas sea una función asíncrona y
crear el conjunto de corrutinas correspondientes.
Se debe crear una lista tareas (tasks) y utilizar la funcionalidad asyn-
cio.gather, que permite ejecutarlas de manera concurrente.

# 2 corrutinas llamadas de manera independiente 'a la vez'


import asyncio

async def holacoro():


for i in range(3):
await asyncio.sleep(1)
print("Hola %d" % i)

async def chaocoro():


for i in range(3):
await asyncio.sleep(2)
print("Chao %d" % i)

8
if __name__ == "__main__":
tasks=[
asyncio.ensure_future(holacoro()),
asyncio.ensure_future(chaocoro())
]
loop = asyncio.get_event_loop()
#creamos tarea y la asociamos al loop, ejecutandola
loop.run_until_complete(
asyncio.gather(*tasks)
)

Esto modo de hacer también tiene sus limitaciones que están por fuera de
su diseño. Se da el caso de que si fuera necesario trabajar con datos en tiempo
real generados por fuentes de datos (sensores) de manera consecutiva. Hay
capacidad que cada trabajador puede atender de manera asíncrona. Cuando
eso sucede es necesario trabajar, además, con múltiples procesos.

2.2.3 Múltiples tareas con llamadas a await internamente.


Si tenemos varias corrutinas que también tienen llamadas a otras corrutinas
internamente, puede suceder que durante la ejecución de estas tareas se libere
el procesador o trabajador para que otra tarea se realice. Puede suceder que
mientras una tarea esté pendiente se termina otra y, al terminar esta última,
continúa la ejecución de la primera tarea. De esta manera puede ocurrir un
sinnúmero de combinaciones posibles que incluso pueden llegar a perjudicar
el proceso general más que beneficiarlo, por eso es necesario saber bien que
se está haciendo y con qué tipo de eventos se está trabajando.

9
En este caso, se observa lo siguiente:

• Tarea 0 se ejecuta y tiene un await intermedio.

• Mientras T0 espera, se ejecuta T1.

• Termina T1, continúa T0.

• Termina T0, continúa T2

• T2 tiene dos intermedios con await

• En cada intermedio se ejecuta T3.

• T0 retoma con una nueva tarea

• En el await de T0 se ejecuta T1

• Al finalizar T0, se ejecuta T2

• En primer await de T2, se ejecuta T1

• En segundo await de T2, se ejecuta T3

• Retoma T0 nuevamente.

• En await de T0, pasa a ejecutarse T2

• Termina la primera parte de T2, hasta await y continúa T0 hasta


terminar.

10
3 Un async while artesanal
Cuando necesitamos una mayor funcionalidad asíncrona, en que necesitemos
que cada corrutina de opere de manera independiente y en un loop, no basta
con poner un while clásico como estructura de control. Tiene que ir un poco
por sobre eso y debe estar a nivel de los objetos tareas Tasks.
La clave de esto es el método add_done_callback, que permite definir
una función que ejecuta nuevamente la misma corrutina.

import asyncio

async def holacoro():


print("Hola %d" % 1)
await asyncio.sleep(1)

def renew(*args):
task = asyncio.ensure_future(holacoro())
task.add_done_callback(renew)

task=asyncio.ensure_future(holacoro())
task.add_done_callback(renew)

loop=asyncio.get_event_loop()

try:
loop.run_forever()
except KeyboardInterrupt:
print('Loop stopped')

Luego, observamos que podemos generalizar un poco más esto y definimos


una función asíncrona que es una máscara de otra, y tiene por argumentos
la otra y los argumentos de esta última.
Además, utilizamos otro módulo de la biblioteca estándar llamado func-
tools Documentación. Este permite definir la función de entrada y sus
argumentos como una función que no necesita argumentos.

import asyncio
import functools

async def holacoro(v):

11
print("Hola %d" % v)
await asyncio.sleep(1)
return v+1

#special for every coroutine


async def coromask(coro, args):
result=await coro(*args)
return [result]

def renew(task, coromask, coro, *args):


print(task.result())
task=asyncio.ensure_future(coromask(coro,task.result()))
task.add_done_callback(
functools.partial(
renew,
task,
coromask,
coro))

args=[1]
task=asyncio.ensure_future(coromask(holacoro,args))
task.add_done_callback(
functools.partial(renew,
task,
coromask,
holacoro))

loop=asyncio.get_event_loop()

try:
loop.run_forever()
except KeyboardInterrupt:
print('Loop stopped')

Con esto, nos damos cuenta que debemos tratar los argumentos de en-
trada así como también las salidas. Esto porque en la próxima iteración tam-
bién debemos tener argumentos que vengan de alguna parte. Estos pueden
ser:

• Argumentos que son siempre la misma entrada

12
• Argumentos que son los que sale de la iteración anterior

• Argumentos que toman la salida y se les opera una función, el resultado


es el argumento o entrada de la próxima iteracion.

import asyncio
import functools

async def holacoro(v):


print("Hola %d" % v)
await asyncio.sleep(1)
return v+1

async def sumacoro(*args):


c=sum(args)
print("La suma es %d" %c)
await asyncio.sleep(3)
return c

#special for every coroutine


async def coromask(coro, args):
result=await coro(*args)
return [result]

#special for every coroutine


async def coromask_suma(coro, args):
_in=[args[-1]]
result=await coro(*args)
_in.append(result)
return _in

def renew(task, mask, coro, *args):


result=task.result()
task=loop.create_task(mask(coro,result))
task.add_done_callback(
functools.partial(renew, task, mask, coro))

loop=asyncio.get_event_loop()

args=[1]

13
task1=asyncio.ensure_future(coromask(holacoro,args))
task1.add_done_callback(
functools.partial(renew, task1, coromask, holacoro))

args2=[1,2]
task2=asyncio.ensure_future(coromask_suma(sumacoro,args2))
task2.add_done_callback(
functools.partial(renew, task2, coromask_suma, sumacoro))

try:
loop.run_forever()
except KeyboardInterrupt:
print('Loop stopped')

De manera más general, se definen las funciones que procesan los argu-
mentos para nuestras funciones asíncronas.

import asyncio
import functools

async def holacoro(v):


print("Hola %d" % v)
await asyncio.sleep(1)
return v+1

async def sumacoro(*args):


c=sum(args)
print("La suma es %d" %c)
await asyncio.sleep(3)
return c

def fargs_holacoro(args, obtained):


return [obtained]

def fargs_sumacoro(args, obtained):


result= [args[-1], obtained]
return result

#every coroutine

14
async def coromask(coro, args, fargs):
_in=args
obtained=await coro(*args)
result=fargs(_in, obtained)
return result

def renew(task, coro, fargs, *args):


result=task.result()
loop=asyncio.get_event_loop()
task=loop.create_task(coromask(coro, result, fargs))
task.add_done_callback(
functools.partial(renew, task, coro, fargs))

loop=asyncio.get_event_loop()

args=[1]
task1=loop.create_task(
coromask(holacoro,args,fargs_holacoro))
task1.add_done_callback(
functools.partial(renew, task1, holacoro, fargs_holacoro))

args2=[1,2]
task2=loop.create_task(
coromask(sumacoro,args2,fargs_sumacoro))
task2.add_done_callback(
functools.partial(renew, task2, sumacoro, fargs_sumacoro))

try:
loop.run_forever()
except KeyboardInterrupt:
print('Loop stopped')

Esto se traducirá entonces en un módulo que tenga disponibles estas


funciones generales para que cualquier función asíncrona que necesitemos
pueda ser ejecutada en un loop independiente, nuestro async while.

import asyncio
import functools

15
#every coroutine
async def coromask(coro, args, fargs):
try:
_in = args
msg = ("Coromask args %s in coro %s" %(args, coro) )
obtained = await coro(*args)
if isinstance(obtained, Exception):
raise Exception()
else:
result = fargs(_in, obtained)
return result
except Exception:
print(msg)
raise Exception

def renew(task, coro, fargs, *args):


if task.exception():
print("Excepcion")
raise task.result()
else:
result = task.result()
loop = asyncio.get_event_loop()
task = loop.create_task(coromask(coro, result, fargs))
task.add_done_callback(functools.partial(renew, task, coro, fargs))

def simple_fargs(_in, obtained):


return _in

def simple_fargs_out(_in, obtained):


return obtained

El módulo que contiene estas cuatro funciones se llama tasktools y se


puede instalar con pip, y su Documentación está disponible en la web.
El patrón de diseño debe considerar lo siguiente.

función asíncrona que se deba repetir en un loop

función entrada que defina cual es la entrada en cada iteración

función task que defina la tarea a repetir

16
En resumen, el esquema que nos habilita nuestro async while es el que
viene a continuación.

4 Clase con métodos asíncronos


Las funciones asíncronas no solo pueden ser implementadas de manera inde-
pendiente, sino también pueden ser un método de una clase que definamos.
Esto nos provee una flexibilidad deseada, nos entrega asíncronismo para los
objetos que necesitamos crear o implementar.
Instalar los siguientes módulos:

pip install networktools


pip install tasktools

Creamos una clase Engine que contenga una serie de métodos asín-
cronos. De la manera siguiente.

17
Además, cada método asíncrono genera un resultado que se comunica
mediante una cola o Queue a otro de los métodos. Por lo que cada iteración
tendrá resultados diferentes que dependen del resultado de la ejecución de
las otras funciones.
Las Queue, son objetos que permiten enviar información de un punto
a otro. Operan como si fuera un cable de comunicación. De esta manera,
desde un punto se envía un dato que se recibe desde otro punto.

import asyncio
import functools
import math
from networktools.time import timestamp
from networktools.colorprint import gprint, \
bprint, rprint
from tasktools.taskloop import coromask,\
renew, simple_fargs, simple_fargs_out

def read_queue(queue):
result=[]
if not queue.empty():
for m in range(queue.qsize()):
result.append(queue.get())
queue.task_done()
return result

async def co_read_queue(queue):


result=[]
if not queue.empty():
for m in range(queue.qsize()):
result.append(await queue.get())
queue.task_done()
return result

def suma_fargs(_in, obtained):


b=_in[0]+.1
_out=[b,_in[1]]
return _out

def resta_fargs(_in, obtained):


b=_in[0]+.1

18
_out=[b,_in[1]]
return _out

class Engine(object):
def __init__(self, *args, **kwargs):
self.a=kwargs['a']
self.b=kwargs['b']
self.w=kwargs['w']
self.mode=kwargs['mode']

#colores::::
#red: suma
#blue: resta
#green: seno

async def suma(self, delta, queue):


result=self.a+delta
bprint(result)
await asyncio.sleep(2)
if not self.mode=='mprocess':
await queue.put(result)
else:
queue.put(result)
return result

async def resta(self, delta, queue):


result=self.b-delta
rprint(result)
await asyncio.sleep(2)
if not self.mode=='mprocess':
await queue.put(result)
else:
queue.put(result)
return result

async def seno(self, queue_suma, queue_resta):


if not self.mode=='mprocess':
r=await co_read_queue(queue_resta)
s=await co_read_queue(queue_suma)
else:

19
r=read_queue(queue_resta)
s=read_queue(queue_suma)
result=0
print(r)
print(s)
if s and r:
amplitude=s[0]/r[0]
ts=timestamp()
result = amplitude * math.sin(self.w*ts)
gprint(result)
await asyncio.sleep(2)
return result

def suma_task(self, queue):


loop=asyncio.get_event_loop()
rprint("Iniciando tarea para Suma")
delta=.3
args= [delta, queue]
# Create instances
task=loop.create_task(
coromask(
self.suma,
args,
suma_fargs)
)
task.add_done_callback(
functools.partial(
renew,
task,
self.suma,
suma_fargs)
)
if not loop.is_running() and self.mode=='mprocess':
loop.run_forever()

def resta_task(self, queue):


loop=asyncio.get_event_loop()
bprint("Iniciando tarea para resta")
delta=.3

20
args= [delta, queue]
# Create instances
task=loop.create_task(
coromask(
self.resta,
args,
resta_fargs)
)
task.add_done_callback(
functools.partial(
renew,
task,
self.resta,
resta_fargs)
)
if not loop.is_running() and self.mode=='mprocess':
loop.run_forever()
pass

def seno_task(self, queue_suma, queue_resta):


loop=asyncio.get_event_loop()
gprint("Iniciando tarea para seno")
args= [queue_suma, queue_resta]
# Create instances
task=loop.create_task(
coromask(
self.seno,
args,
simple_fargs)
)
task.add_done_callback(
functools.partial(
renew,
task,
self.seno,
simple_fargs)
)
if not loop.is_running() and self.mode=='mprocess':
loop.run_forever()

21
4.1 Ejecución en un proceso.
Nuestra clase Engine puede ser llamada desde un solo trabajador (loop) de
la manera siguiente.

import asyncio
from engine import Engine

if __name__ == "__main__":
loop = asyncio.get_event_loop()
queue_suma=asyncio.Queue()
queue_resta=asyncio.Queue()
a=2
b=3
w=.05
engine=Engine(a=a,b=b,w=w, mode='async')
engine.suma_task(queue_suma)
engine.resta_task(queue_resta)
engine.seno_task(queue_suma,queue_resta)
loop.run_forever()

4.2 Ejecución en múltiples procesos.


Cuando necesitamos habilitar varios procesos o trabajadores atentos a ciertas
tareas, se procede de la manera siguiente.
Se activa una serie de procesos (procesadores o núcleos de la CPU) para
atender tareas específicas. Este conjunto se llama pool executor, y hay
que asignarle a cada procesador disponible sus tareas.

import asyncio
import functools
import concurrent.futures
from engine import Engine
from multiprocessing import Manager, Queue

if __name__ == "__main__":
loop = asyncio.get_event_loop()
manager=Manager()
queue_suma=manager.Queue()
queue_resta=manager.Queue()

22
a=2
b=3
w=.05
engine=Engine(a=a,b=b,w=w, mode='mprocess')
with concurrent.futures.ProcessPoolExecutor() as executor:
def suma_process():
print(engine)
engine.suma_task(queue_suma)

def resta_process():
print(engine)
engine.resta_task(queue_resta)

def seno_process():
print(engine)
engine.seno_task(queue_suma,queue_resta)

loop.run_in_executor(
executor,
#functools.partial(engine.suma_task,queue_suma)
suma_process
)
loop.run_in_executor(
executor,
resta_process
)
loop.run_in_executor(
executor,
seno_process
)
#await engine.resta_task(queue_resta)
#await engine.seno_task(queue_suma, queue_resta)
loop.run_forever()

5 Proyectos de Interés
Entre los proyectos de interés realizados por quien realizó esta guia, con
asyncio puedes ver:

tasktools implementación de async while, un agendador y asignador de

23
tareas. Gitlab

Networktools funciones de utilidad. Gitlab

gnsocket implementación de socket de comunicación TCP/IP asíncrono.


Gitlab

collector sistema para la adquisición de datos de una red de estaciones


GPS. Gitlab

datawork sistema para procesar estos datos. Gitlab

socketmanager sistema para gestionar servicios que tienen sockets. Conecta


la administación humana con collector y datawork. [En desarrollo]

6 Conocimiento recomendado
David Beaz http://www.dabeaz.com/

WillysCave Blog

MichaelKuty http://michaelkuty.github.io/vertx-gdg/#/

David Pineda https://gitlab.com/pineiden/async_coro

Módulos de mucha gente https://github.com/python/asyncio/wiki/


ThirdParty

24

También podría gustarte