Programação assíncrona em Python

Mar 06 2023
A programação assíncrona é um paradigma de programação que permite que muitos processos sejam executados simultaneamente e independentemente, sem esperar que um termine antes de prosseguir para o próximo. Nesta postagem do blog, veremos o que é programação assíncrona e como usá-la em python.
Programação assíncrona em Python

A programação assíncrona é um paradigma de programação que permite que muitos processos sejam executados simultaneamente e independentemente, sem esperar que um termine antes de prosseguir para o próximo. Nesta postagem do blog, veremos o que é programação assíncrona e como usá-la em python.

O que é Programação Assíncrona?

Na programação síncrona, o computador executa as instruções em ordem sequencial, bloqueando a execução até que um trabalho seja concluído antes de passar para o próximo.
A programação assíncrona, por outro lado, permite que o programa inicie uma operação e depois passe para outra sem interromper a execução até que a tarefa original seja concluída.

A programação assíncrona é especialmente benéfica em circunstâncias em que processos, como E/S de rede ou operações de banco de dados, podem levar muito tempo para serem concluídos. A programação assíncrona pode ajudar a aumentar o desempenho e a capacidade de resposta em aplicativos de software, permitindo que o programa passe para outras atividades enquanto espera a conclusão de uma operação lenta.

Dependendo da linguagem de programação e da estrutura usada, a programação assíncrona pode ser realizada usando várias estratégias, como retornos de chamada, promessas ou palavras-chave async/await.

Diferenças entre programação assíncrona e multiprocessamento

A principal diferença entre a programação assíncrona e o multiprocessamento é que a programação assíncrona permite que operações sem bloqueio ocorram em um único thread, enquanto o multiprocessamento usa muitos núcleos ou processos para concluir o trabalho simultaneamente.

Diferenças entre programação assíncrona e threading

A principal diferença entre a programação assíncrona e o threading é que a programação assíncrona permite operações sem bloqueio usando um único thread, enquanto o threading usa vários threads para executar várias tarefas em paralelo.

Para mais informações sobre as diferenças: Treading vs Multiprocessing vs Programação Assíncrona

Como usar o Assincio?

Primeiro vamos fazer um programa simples que começa a fazer um trabalho de cada vez e os finaliza.

import time
import asyncio

def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    for job in todo:
        do_job(job)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

main()

# OUTPUT
# Job A started
# Job Adone
# Job B started
# Job B done
# Job C started
# Job C done
# Took: 3.009 seconds

Criando e executando corrotinas

Uma co-rotina é um tipo de função que pode ser interrompida e retomada várias vezes durante a execução. Em outras palavras, uma co-rotina permite que você escreva um código que pode ser interrompido, faça outra coisa e continue de onde parou.

Para criar corrotinas, precisamos usar a asyncpalavra-chave antes da defpalavra-chave. Chamar uma co-rotina não chama a função que queremos executar. Ele cria uma tarefa.

import time
import asyncio

async def do_job(s):
  ...

async def main():
  ...

main()

asyncio.run(main())

se você executar este código, provavelmente receberá um erro como este:

RuntimeWarning: coroutine '...' was never awaited

import time
import asyncio

async def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

async def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    for job in todo:
        await do_job(job)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

asyncio.run(main())

# OUTPUT
# Job A started
# Job A done
# Job B started
# Job B done
# Job C started
# Job C done
# Took: 3.009 seconds

await asyncio.sleep(1)

tasks = [asyncio.create_task(do_job(item)) for item in todo]
done, pending = await asyncio.wait(tasks)

import time
import asyncio

async def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

async def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    
    tasks = [asyncio.create_task(do_job(item)) for item in todo]
    done, pending = await asyncio.wait(tasks)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

asyncio.run(main())

# OUTPUT
# Job A started
# Job B started
# Job C started
# Job A done
# Job B done
# Job C done
# Took: 1.009 seconds

Você pode assistir ao vídeo para obter mais informações sobre programação assíncrona em python. ( Introdução ao Python assíncrono | Escrevendo um rastreador da Web )