Blog

Postado em em 16 de maio de 2023

Programação Assíncrona em Python – AsyncIO e Await

Quer aprender sobre programação assíncrona em Python? Descubra nesta aula como é feita a mudança de processo em um código!

Caso prefira esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!

Para receber por e-mail o(s) arquivo(s) utilizados na aula, preencha:

Fala Impressionadores! Você já ouviu falar em programação assíncrona em Python? Sabe o que é e como funciona?

Hoje eu vou te mostrar o que é programação assíncrona e ainda vou te mostrar um exemplo prático para que você entenda em quais casos vai utilizar essa programação.

Essa programação é diferente do que você está acostumado, pois não vamos ter linha a linha de código executando uma depois da outra. A ideia aqui é, ganhar tempo enquanto o seu código está parado em outra função.

Então enquanto o seu código está esperando uma requisição, ou esperando alguma ação ser concluída, você vai conseguir executar outras partes do seu código. Isso considerando que elas são independentes, ou seja, não precisa de uma para executar a outra.

Sabendo disso vou te ensinar como usar o async e await em Python para criar um código assíncrono que vai executar o código dessa forma.

Guia de aprendizado

Essa estrutura de programação assíncrona é relativamente recente no Python, sendo lançada somente após a versão 3.4 do Python.

Por ser recente e mais complexa, não recomendo focar nela logo no começo do aprendizado, é melhor antes, tornar-se experiente na lógica do Python e em seu uso mais comum, só depois passar para esse aprendizado que é mais complexo.

Mas, o que é Programação Assíncrona e qual a diferença entre ela e as outras formas de programar?

Programação Síncrona

Normalmente o Python executa a primeira linha de código, depois a segunda, a terceira, quarta e assim sucessivamente.

Essencialmente o Python espera uma linha de código acabar de ser executada para só então começar a executar a próxima, isso é o que chamamos de programação síncrona.

Paralelismo

Existe outro processo chamado de paralelismo, neste caso ao invés de esperar um processo acabar para então começar o outro, ambos os processos são executados em paralelo, no mesmo segundo.

Programação Assíncrona

A programação assíncrona parece com o paralelismo, mas nela você não vai rodar dois processos ao mesmo tempo.

Você vai rodar 1 processo e a medida que ele estiver rodando pode acontecer de ele travar ou ficar em espera por algum motivo. Quando isso acontece se inicia um segundo processo assíncrono.

Exemplificando:

  • Para entender melhor, imagine que você está jogando duas partidas de xadrez ao mesmo tempo, no processo síncrono você vai jogar um jogo e após terminar você começa o segundo jogo.
  • No paralelismo você joga os dois jogos juntos fazendo duas jogadas sempre no mesmo segundo e depois aguardando a jogada do oponente.
  • No modo Assíncrono você faz uma jogada e enquanto o oponente está pensando na resposta você vai para o outro jogo e executa uma jogada, ou seja, você segue aproveitando todos os tempos de espera.

O processo assíncrono consegue ser o mais eficiente porque além de economizar o tempo ele não gasta tanto recurso de dividir a atenção como no paralelismo para ter que fazer duas coisas diferentes no mesmo segundo.

Exemplo prático

Imagine que você está fazendo o fechamento mensal da sua empresa, neste processo vários cálculos devem ser feitos como, o imposto a ser pago, hora extra, bônus para os funcionários, etc.

Neste exemplo vamos calcular o imposto e o bônus dos funcionários.

Esses processos não dependem um do outro, o imposto depende do faturamento enquanto o bônus depende das vendas que foram feitas.

Embora os dois processos não dependam um do outro para acontecer, para fazer o fechamento ambos devem estar concluídos.

Exemplo:

import time

def calcular_imposto(faturamento):

    print(faturamento * 0.1)

def calcular_bonus_funcionarios(vendas):

    for funcionario in vendas:

        venda = vendas[funcionario]

        print(funcionario, "Bonus:", venda * 0.05)

        time.sleep(1)

def fechamento():

    vendas = {

        "lira": 1500,

        "joao": 500,

        "amanda": 5000

    }

    faturamento = 1000

    calcular_bonus_funcionarios(vendas)

    calcular_imposto(faturamento)

    print("Finalizou")

fechamento()

O processo utilizado neste código é o processo Síncrono, quando você rodar o código vai perceber que ele executa cada ação uma de cada vez e uma se inicia logo após a outra. Não é um processo muito rápido.

Neste código para simular o tempo de espera entre um processo e outro usamos o time.sleep(1), esse tempo pode ser o tempo que o sistema da empresa demora para carregar ou qualquer outro processo que gere um tempo de resposta.

Este segundo de espera é o que a programação Assíncrona irá aproveitar para calcular o imposto, por exemplo, o imposto independe dos outros processos e pode ser adiantado.

Tornando o processo Assíncrono

Para tornar o processo assíncrono o primeiro passo é importar a biblioteca asyncio, o segundo passo é tornar as funções que estão rodando o processo como funções assíncronas para isso vamos escrever antes de cada função a palavra async.

Também temos que modificar o comando time.sleep(1) este comando faz com que todos os processos, assíncronos ou não, tenham que aguardar 1 segundo antes de prosseguir.

Vamos trocar este comando para -> await asyncio.sleep(1), dessa forma enquanto um processo espera, outro processo pode começar a aproveitar o tempo, além disso, o comando asyncio.sleep(1) funciona somente para uma função onde colocamos ele não para todo o código.

No final, na hora de chamar a função fechamento você deve chamá-la da seguinte forma asyncio.run(fechamento()), assim o Python vai rodar o fechamento com um gerenciador de processos assíncronos.

Este gerenciador é quem vai se preocupar com a lógica de aproveitar os espaços de tempo de espera para rodar outros processos de forma assíncrona.

Observações importantes:

Agora temos que rodar a função, mas a função assíncrona não roda da forma normal como todas as outras, se você apenas rodar vai retornar um erro.

Para executá-la temos que criar uma tarefa assíncrona para cada uma das funções, exemplo:

tarefa = asyncio.create_task(calcular_bonus_funcionarios(vendas))

Após isso, quando rodamos, pode acontecer da função retornar o valor Finalizado antes mesmo de rodar totalmente o cálculo dos impostos e bônus.

Isso acontece porque essas funções não estão dentro do fechamento e não temos nenhum comando informando que a função deve aguardar o término dessas tarefas, o que pode gerar outro erro.

Então, sempre que uma tarefa gera um valor como resultado, devemos colocar um comando de espera no final logo após o print await tarefa para que o gerenciador saiba que é necessário concluir a tarefa por completo antes de finalizar os processos assíncronos.

Para ficar mais claro, observe as mudanças no código abaixo:

import asyncio

import time

async def calcular_imposto(faturamento):

    print(faturamento * 0.1)

async def calcular_bonus_funcionarios(vendas):

    for funcionario in vendas:

        venda = vendas[funcionario]

        print(funcionario, "Bonus:", venda * 0.05)

        await asyncio.sleep(1)

async def fechamento():

    vendas = {

        "lira": 1500,

        "joao": 500,

        "amanda": 5000

    }

    faturamento = 1000

    tarefa = asyncio.create_task(calcular_bonus_funcionarios(vendas))

    tarefa2 = asyncio.create_task(calcular_imposto(faturamento))

    print("Finalizou")

    await tarefa

    await tarefa2

asyncio.run(fechamento())

Agora quando rodar o código ele vai executar primeiro o print -> finalizou

Após, ele começa a rodar o bônus e no tempo de espera ele aproveita e calcula o imposto.

Após, ele retornar para calcular o bônus.

Conclusão – Programação Assíncrona em Python

Podemos concluir que o processo assíncrono é o que mais otimiza o tempo de execução dos processos, muitos Frameworks que utilizamos já foram construídos dentro deste processo assíncrono para otimizar os seus processos.

Mesmo assim, pode acontecer de você precisar otimizar um processo seu na sua empresa e neste caso esta aula vai te ajudar muito.

Novamente, eu recomendo que antes de se aprofundar em processos assíncronos você estude bem a lógica dos processos mais comuns no Python.

Isso porque é mais complexo entender a ordem de execução dos processos assíncronos e a lógica usada nos processos síncronos deve estar muito bem fixada na sua cabeça antes de tentar entender os assíncronos.

Espero que tenha gostado do conteúdo! Até a próxima! Abraço,

Hashtag Treinamentos

Para acessar outras publicações de Python, clique aqui!


Quer aprender mais sobre Python com um minicurso básico gratuito?

Quer sair do zero no Power BI e virar uma referência na sua empresa? Inscreva-se agora mesmo no Power BI Impressionador