Uma co-rotina é uma função geradora que pode produzir valores e aceitar valores externos. O benefício de usar uma co-rotina é que podemos pausar a execução de uma função e retomá-la mais tarde. No caso de uma operação de rede, faz sentido pausar a execução de uma função enquanto esperamos pela resposta. Podemos usar o tempo para executar algumas outras funções.
Um futuro é como os Promise
objetos de Javascript. É como um espaço reservado para um valor que se materializará no futuro. No caso mencionado acima, enquanto espera pela E / S da rede, uma função pode nos dar um contêiner, uma promessa de que preencherá o contêiner com o valor quando a operação for concluída. Nós nos agarramos ao objeto futuro e quando ele for cumprido, podemos chamar um método nele para recuperar o resultado real.
Resposta direta: Você não precisa, ensure_future
se não precisa dos resultados. Eles são bons se você precisar dos resultados ou recuperar exceções ocorridas.
Créditos extras: eu escolheria run_in_executor
e aprovaria uma Executor
instância para controlar o número máximo de trabalhadores.
Explicações e códigos de amostra
No primeiro exemplo, você está usando corrotinas. A wait
função pega um monte de co-rotinas e as combina. Então wait()
termina quando todas as co-rotinas estiverem esgotadas (concluído / terminado retornando todos os valores).
loop = get_event_loop() #
loop.run_until_complete(wait(coros))
O run_until_complete
método garantiria que o loop estivesse ativo até que a execução fosse concluída. Observe como você não está obtendo os resultados da execução assíncrona neste caso.
No segundo exemplo, você está usando a ensure_future
função para envolver uma co-rotina e retornar um Task
objeto que é uma espécie de Future
. A corrotina está programada para ser executada no loop de evento principal quando você chama ensure_future
. O objeto futuro / tarefa retornado ainda não tem um valor, mas com o tempo, quando as operações de rede terminarem, o objeto futuro conterá o resultado da operação.
from asyncio import ensure_future
futures = []
for i in range(5):
futures.append(ensure_future(foo(i)))
loop = get_event_loop()
loop.run_until_complete(wait(futures))
Portanto, neste exemplo, estamos fazendo a mesma coisa, exceto que estamos usando futuros em vez de apenas usar corrotinas.
Vejamos um exemplo de como usar asyncio / corroutines / futures:
import asyncio
async def slow_operation():
await asyncio.sleep(1)
return 'Future is done!'
def got_result(future):
print(future.result())
# We have result, so let's stop
loop.stop()
loop = asyncio.get_event_loop()
task = loop.create_task(slow_operation())
task.add_done_callback(got_result)
# We run forever
loop.run_forever()
Aqui, usamos o create_task
método no loop
objeto. ensure_future
iria agendar a tarefa no loop de evento principal. Este método nos permite agendar uma co-rotina em um loop que escolhermos.
Também vemos o conceito de adicionar um retorno de chamada usando o add_done_callback
método no objeto de tarefa.
A Task
é done
quando a co-rotina retorna um valor, levanta uma exceção ou é cancelada. Existem métodos para verificar esses incidentes.
Escrevi algumas postagens de blog sobre esses tópicos que podem ajudar:
Claro, você pode encontrar mais detalhes no manual oficial: https://docs.python.org/3/library/asyncio.html
ensure_future()
? E se eu precisar do resultado, não posso simplesmente usarrun_until_complete(gather(coros))
?