Informazioni effettive:
A questo scopo, a partire da Python 3.7 asyncio.create_task(coro)
, è stata aggiunta la funzione di alto livello .
Dovresti usarlo invece in altri modi per creare attività da coroutimes. Tuttavia, se è necessario creare un'attività da attesa arbitraria, è necessario utilizzare asyncio.ensure_future(obj)
.
Vecchie informazioni:
ensure_future
vs create_task
ensure_future
è un metodo per creare Task
da coroutine
. Crea attività in modi diversi in base all'argomento (incluso l'uso di create_task
per coroutine e oggetti simili al futuro).
create_task
è un metodo astratto di AbstractEventLoop
. Cicli di eventi diversi possono implementare questa funzione in modi diversi.
Dovresti usare ensure_future
per creare attività. Ne avrai bisogno create_task
solo se intendi implementare il tuo tipo di loop di eventi.
Aggiornare:
@ bj0 ha indicato la risposta di Guido su questo argomento:
Il punto ensure_future()
è che se hai qualcosa che potrebbe essere una coroutine o a Future
(quest'ultimo include a Task
perché è una sottoclasse di Future
), e vuoi essere in grado di chiamare un metodo su di esso che è definito solo su Future
(probabilmente circa l'unico essere utile esempio cancel()
). Quando è già un Future
(o Task
) questo non fa nulla; quando è una coroutine la avvolge in una Task
.
Se sai di avere una coroutine e vuoi che sia pianificata, l'API corretta da usare è create_task()
. L'unico momento in cui dovresti chiamare ensure_future()
è quando fornisci un'API (come la maggior parte delle API di asyncio) che accetta una coroutine o a Future
e devi fare qualcosa che richiede di avere un file Future
.
e più tardi:
Alla fine credo ancora che ensure_future()
sia un nome adeguatamente oscuro per una parte di funzionalità raramente necessaria. Quando crei un'attività da una coroutine dovresti usare il nome appropriato
loop.create_task()
. Forse dovrebbe esserci un alias per questo
asyncio.create_task()
?
È sorprendente per me. La mia motivazione principale da utilizzare è ensure_future
stata che si tratta di una funzione di livello superiore rispetto al membro del ciclo create_task
(la discussione contiene alcune idee come l'aggiunta di asyncio.spawn
o asyncio.create_task
).
Posso anche sottolineare che a mio parere è abbastanza conveniente usare la funzione universale che può gestire qualsiasi Awaitable
piuttosto che solo le coroutine.
Tuttavia, la risposta di Guido è chiara: "Quando crei un'attività da una coroutine dovresti usare il nome appropriato loop.create_task()
"
Quando le coroutine dovrebbero essere inserite nelle attività?
Avvolgere la coroutine in un'attività: è un modo per avviare questa coroutine "in background". Ecco un esempio:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Produzione:
first
long_operation started
second
long_operation finished
Puoi sostituire asyncio.ensure_future(long_operation())
con solo await long_operation()
per sentire la differenza.
create_task
se hai davvero bisogno di un oggetto attività, che normalmente non dovresti aver bisogno: github.com/python/asyncio/issues/477#issuecomment-268709555