Digamos que tenemos una función ficticia:
async def foo(arg):
result = await some_remote_call(arg)
return result.upper()
Cuál es la diferencia entre:
import asyncio
coros = []
for i in range(5):
coros.append(foo(i))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coros))
Y:
import asyncio
futures = []
for i in range(5):
futures.append(asyncio.ensure_future(foo(i)))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(futures))
Nota : El ejemplo devuelve un resultado, pero este no es el foco de la pregunta. Cuando el valor de retorno importa, use en gather()
lugar de wait()
.
Independientemente del valor de retorno, busco claridad ensure_future()
. wait(coros)
y wait(futures)
ambos ejecutan las corrutinas, entonces, ¿cuándo y por qué debería incluirse una corrutina ensure_future
?
Básicamente, ¿cuál es la forma correcta (tm) de ejecutar un montón de operaciones sin bloqueo usando Python 3.5 async
?
Para obtener crédito adicional, ¿qué sucede si quiero agrupar las llamadas? Por ejemplo, necesito llamar some_remote_call(...)
1000 veces, pero no quiero aplastar el servidor web / base de datos / etc.con 1000 conexiones simultáneas. Esto es factible con un hilo o grupo de procesos, pero ¿hay alguna forma de hacerlo asyncio
?
Actualización 2020 (Python 3.7+) : no use estos fragmentos. En su lugar use:
import asyncio
async def do_something_async():
tasks = []
for i in range(5):
tasks.append(asyncio.create_task(foo(i)))
await asyncio.gather(*tasks)
def do_something():
asyncio.run(do_something_async)
También considere usar Trio , una alternativa sólida de terceros a asyncio.
ensure_future()
? Y si necesito el resultado, ¿no puedo usarlorun_until_complete(gather(coros))
?