Resumo : neste tutorial, você aprenderá como usar asyncio.create_task()
a função para executar várias tarefas simultaneamente.
Simulando uma operação de longa duração
Para simular uma operação de longa duração, você pode usar a
corrotina do sleep()
asyncio
pacote. A
função atrasa um número especificado de segundos:sleep()
await asyncio.sleep(seconds)
Linguagem de código: Python ( python )
Por
ser uma corrotina, você precisa usar a sleep()
await
palavra-chave. Por exemplo, o seguinte usa a
corrotina para simular uma chamada de API:sleep()
import asyncio
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
Linguagem de código: Python ( python )
É call_api()
uma rotina. Ele exibe uma mensagem, pausa um número especificado de segundos (o padrão é três segundos) e retorna um resultado.
O programa a seguir usa call_api()
duas vezes e mede o tempo que leva para ser concluído:
import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
start = time.perf_counter()
price = await call_api('Get stock price of GOOG...', 300)
print(price)
price = await call_api('Get stock price of APPL...', 400)
print(price)
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())
Linguagem de código: Python ( python )
Saída:
Get stock price of GOOG...
300
Get stock price of APPL...
400
It took 6.0 second(s) to complete.
Linguagem de código: Python ( python )
Como funciona (com foco na main()
corrotina):
Primeiro, inicie um cronômetro para medir o tempo usando a perf_counter()
função do time
módulo:
start = time.perf_counter()
Linguagem de código: Python ( python )
Segundo, chame a call_api()
corrotina e exiba o resultado:
price = await call_api('Get stock price of GOOG...', 300)
print(price)
Linguagem de código: Python ( python )
Terceiro, ligue pela call_api()
segunda vez:
price = await call_api('Get stock price of APPL...', 400)
print(price)
Linguagem de código: Python ( python )
Por fim, mostre o tempo que o programa leva para ser concluído:
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
Linguagem de código: Python ( python )
Porque cada um call_api()
leva três segundos e chamá-lo duas vezes leva seis segundos.
Neste exemplo, chamamos uma corrotina diretamente e não a colocamos no loop de eventos para execução. Em vez disso, obtemos um objeto de rotina e usamos a await
palavra-chave para executá-lo e obter um resultado.
A imagem a seguir ilustra o fluxo de execução do programa:
Em outras palavras, usamos async
e await
para escrever código assíncrono, mas não podemos executá-lo simultaneamente. Para executar múltiplas operações simultaneamente, precisaremos usar algo chamado tarefas.
Introdução às tarefas Python
Uma tarefa é um wrapper de uma corrotina que agenda a corrotina para ser executada no loop de eventos o mais rápido possível.
O agendamento e a execução ocorrem de maneira não bloqueante. Em outras palavras, você pode criar uma tarefa e executar outro código instantaneamente enquanto a tarefa está em execução.
Observe que a tarefa é diferente da await
palavra-chave que bloqueia toda a corrotina até que a operação seja concluída com um resultado.
É importante que você possa criar diversas tarefas e agendá-las para serem executadas instantaneamente no loop de eventos ao mesmo tempo.
Para criar uma tarefa, você passa uma corrotina para a
função do create_task()
asyncio
pacote. A
função retorna um create_task()
Task
objeto.
O programa a seguir ilustra como criar duas tarefas que agendam e executam a call_api()
corrotina:
import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
start = time.perf_counter()
task_1 = asyncio.create_task(
call_api('Get stock price of GOOG...', 300)
)
task_2 = asyncio.create_task(
call_api('Get stock price of APPL...', 300)
)
price = await task_1
print(price)
price = await task_2
print(price)
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())
Linguagem de código: Python ( python )
Saída:
Get stock price of GOOG...
Get stock price of APPL...
300
300
It took 3.0 second(s) to complete.
Linguagem de código: Python ( python )
Como funciona.
Primeiro, inicie um cronômetro:
start = time.perf_counter()
Linguagem de código: Python ( python )
Em seguida, crie uma tarefa e agende-a para ser executada imediatamente no loop de eventos:
task_1 = asyncio.create_task(
call_api('Get stock price of GOOG...', 300)
)
Linguagem de código: Python ( python )
Em seguida, crie outra tarefa e agende-a para ser executada imediatamente no loop de eventos:
task_2 = asyncio.create_task(
call_api('Get stock price of APPL...', 400)
)
Linguagem de código: Python ( python )
Depois disso, aguarde a conclusão das tarefas:
price = await task_1
print(price)
price = await task_2
print(price)
Linguagem de código: Python ( python )
É importante utilizar a await
palavra-chave para aguardar as tarefas em algum momento do programa.
Se não usássemos a await
palavra-chave, o Python agendaria a execução da tarefa, mas a interromperia quando asyncio.run()
o loop de eventos fosse encerrado.
A imagem a seguir ilustra o fluxo de execução do programa:
Por fim, mostre o tempo que leva para completar a main()
função:
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
Linguagem de código: Python ( python )
Ao usar a create_task()
função, o programa fica muito mais rápido. Quanto mais tarefas você executa, mais rápido será.
Executando outras tarefas enquanto espera
Quando o call_api
estiver em execução, você poderá executar outras tarefas. Por exemplo, o programa a seguir exibe uma mensagem a cada segundo enquanto aguarda as call_api
tarefas:
import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def show_message():
for _ in range(3):
await asyncio.sleep(1)
print('API call is in progress...')
async def main():
start = time.perf_counter()
message_task = asyncio.create_task(
show_message()
)
task_1 = asyncio.create_task(
call_api('Get stock price of GOOG...', 300)
)
task_2 = asyncio.create_task(
call_api('Get stock price of APPL...', 300)
)
price = await task_1
print(price)
price = await task_2
print(price)
await message_task
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())
Linguagem de código: Python ( python )
Saída:
Get stock price of GOOG...
Get stock price of APPL...
API call is in progress...
API call is in progress...
API call is in progress...
300
300
Linguagem de código: Python ( python )
A imagem a seguir ilustra o fluxo de execução:
Resumo
- Uma tarefa é um wrapper de uma corrotina que agenda a corrotina para ser executada no loop de eventos o mais rápido possível.
- Use a
create_task()
função daasyncio
biblioteca para criar uma tarefa. - Use a
await
palavra-chave com a tarefa em algum ponto do programa para que a tarefa possa ser concluída antes que o loop de eventos seja fechado pelaasyncio.run()
função.