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 Taskda coroutine. Crea attività in modi diversi in base all'argomento (incluso l'uso di create_taskper 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_futureper creare attività. Ne avrai bisogno create_tasksolo 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 Taskperché è 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 Futuree 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_futurestata 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.spawno asyncio.create_task).
Posso anche sottolineare che a mio parere è abbastanza conveniente usare la funzione universale che può gestire qualsiasi Awaitablepiuttosto 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_taskse hai davvero bisogno di un oggetto attività, che normalmente non dovresti aver bisogno: github.com/python/asyncio/issues/477#issuecomment-268709555