Informação real:
A partir do Python 3.7 asyncio.create_task(coro), a função de alto nível foi adicionada para esse propósito.
Você deve usá-lo em vez de outras maneiras de criar tarefas de co-rotinas. No entanto, se você precisar criar uma tarefa arbitrária, deve usar asyncio.ensure_future(obj).
Informação antiga:
ensure_future vs create_task
ensure_futureé um método para criar Taska partir de coroutine. Ele cria tarefas de maneiras diferentes com base em argumentos (incluindo o uso decreate_task para co-rotinas e objetos semelhantes ao futuro).
create_task é um método abstrato de AbstractEventLoop . Loops de eventos diferentes podem implementar essa função de maneiras diferentes.
Você deve usar ensure_futurepara criar tarefas. Você precisarácreate_task apenas se for implementar seu próprio tipo de loop de evento.
Upd:
@ bj0 apontou para a resposta de Guido sobre este assunto:
O ponto de ensure_future()é se você tem algo que poderia ser uma co-rotina ou um Future(o último inclui um Taskporque é uma subclasse de Future), e você deseja ser capaz de chamar um método nele que está definido apenas em Future(provavelmente sobre o único exemplo útil sendo cancel()). Quando já é um Future(ou Task), isso não faz nada; quando é uma co-rotina, envolve -a em a Task.
Se você sabe que tem uma co-rotina e deseja que ela seja agendada, a API correta a ser usada é create_task(). O único momento em que você deve chamar ensure_future()é quando está fornecendo uma API (como a maioria das próprias APIs do asyncio) que aceita uma co-rotina ou a Futuree você precisa fazer algo que exija que você tenha uma Future.
e depois:
No final, eu ainda acredito que ensure_future() é um nome apropriadamente obscuro para uma funcionalidade raramente necessária. Ao criar uma tarefa a partir de uma co-rotina, você deve usar o nome apropriado
loop.create_task(). Talvez devesse haver um apelido para isso
asyncio.create_task()?
É surpreendente para mim. Minha principal motivação para usar o tempo ensure_futuretodo foi que é uma função de nível superior em comparação com o membro do loopcreate_task (a discussão contém algumas idéias como adicionar asyncio.spawnouasyncio.create_task ).
Também posso apontar que, na minha opinião, é muito conveniente usar uma função universal que pode lidar com qualquer Awaitable vez de apenas co-rotinas.
No entanto, a resposta de Guido é clara: "Ao criar uma tarefa a partir de uma co-rotina, você deve usar o nome apropriadoloop.create_task() "
Quando as corrotinas devem ser envolvidas nas tarefas?
Envolva a co-rotina em uma Tarefa - é uma maneira de iniciar esta co-rotina "em segundo plano". Aqui está um exemplo:
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())
Resultado:
first
long_operation started
second
long_operation finished
Você pode substituir asyncio.ensure_future(long_operation())apenas await long_operation()para sentir a diferença.
create_taskse realmente precisar de um objeto de tarefa, que normalmente não deveria: github.com/python/asyncio/issues/477#issuecomment-268709555