Diciamo di avere una funzione fittizia:
async def foo(arg):
result = await some_remote_call(arg)
return result.upper()
Qual è la differenza tra:
import asyncio
coros = []
for i in range(5):
coros.append(foo(i))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coros))
E:
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 : l'esempio restituisce un risultato, ma questo non è il fulcro della domanda. Quando il valore restituito è importante, usa gather()invece di wait().
Indipendentemente dal valore di ritorno, cerco chiarezza ensure_future(). wait(coros)ed wait(futures)entrambi eseguono le coroutine, quindi quando e perché dovrebbe essere avvolta una coroutine ensure_future?
Fondamentalmente, qual è il modo giusto (tm) per eseguire un mucchio di operazioni non bloccanti usando Python 3.5 async?
Per un credito extra, cosa succede se voglio raggruppare le chiamate? Ad esempio, devo chiamare some_remote_call(...)1000 volte, ma non voglio schiacciare il server web / database / ecc. Con 1000 connessioni simultanee. Questo è fattibile con un thread o un pool di processi, ma esiste un modo per farlo asyncio?
Aggiornamento 2020 (Python 3.7+) : non utilizzare questi snippet. Usa invece:
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)
Considera anche l'utilizzo di Trio , una robusta alternativa di terze parti ad asyncio.
ensure_future()? E se ho bisogno del risultato, non posso semplicemente usarlorun_until_complete(gather(coros))?