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))
?