Alura > Cursos de Programação > Cursos de Python > Conteúdos de Python > Primeiras aulas do curso FastAPI e Python: construindo APIs com autenticação, banco de dados e deploy

FastAPI e Python: construindo APIs com autenticação, banco de dados e deploy

Primeiros Passos com FastAPI e Programação Assíncrona - Introdução FastAPI

Introduzindo o FastAPI

Olá, bem-vindo ao curso de FastAPI. Hoje, vamos aprender o que é FastAPI. Para isso, abrimos a documentação de FastAPI no navegador, que está disponível em fastapi.tiangolo.com. Para quem não sabe, Tiangolo é o nome de usuário no GitHub de Sebastián Ramírez, o criador do FastAPI.

Vamos explorar o que o FastAPI faz e do que é capaz. Para começar, temos uma breve descrição: é de alto desempenho, fácil de aprender, fácil de programar e pronto para produção. Duas características interessantes que podemos destacar são o alto desempenho, graças à execução assíncrona em Python, e o fato de estar pronto para produção. Não requer configuração adicional ou instalação de bibliotecas extras para ser utilizado em produção. Assim que instalamos, já podemos implantar uma aplicação funcional no mesmo dia, com documentação, validações simples ou mais avançadas, se desejarmos, e funcionando da melhor maneira possível, focando no alto desempenho.

Explorando as características do FastAPI

Vamos ler um pouco mais abaixo, onde há uma seção mais descritiva com algumas palavras-chave. Novamente, destaca-se o alto desempenho. O FastAPI é um framework web que constrói tanto a parte de API, podendo ser considerado para back-end, mas também pode entregar front-end usando um framework e um motor chamado Jinja, permitindo a criação de templates HTML.

Por que o FastAPI é tão bom? Ele utiliza uma característica padrão do Python, que são os type hints (dicas de tipo), permitindo definir o tipo de uma variável. Embora o Python não seja tipado, podemos indicar que uma variável é do tipo string, por exemplo. Sob o capô, o FastAPI utiliza o Pydantic, que é usado para criar classes e objetos já tipados, garantindo que haverá certa validação. Assim, se definirmos um campo como string, podemos confiar que ele será tratado como tal.

Detalhando a infraestrutura do FastAPI

Abaixo do capô, na parte do motor, utilizamos o Starlette, que é uma biblioteca amplamente utilizada em Python para a parte web. Graças a isso, podemos nos aproximar de ser equivalentes, e às vezes até melhores, que Node e Go. Uma vantagem é a redução de bugs, pois codificamos menos e não precisamos criar uma grande quantidade de código para colocar algo em produção. Isso garante menos bugs, já que nos preocupamos com menos código. Além disso, possui uma documentação padrão. Assim, ao implementar nossa própria API, podemos facilmente compartilhá-la com colegas, outros times ou áreas, mostrando o que a API faz, o que espera como entrada e o que envia como saída. Tudo isso é o que o FastAPI pode oferecer, e veremos muito mais nos próximos vídeos.

Analisando as necessidades do cliente

Vamos analisar o que nosso cliente, Techlog Solutions, necessita e por que nos contratou. No momento, estamos com o VSCode aberto, visualizando o arquivo de README em modo de visualização para que fique mais apresentável. Precisamos criar um site para registrar clientes e suas ordens de serviço, o que é praticamente um CRM, um serviço de gestão de relacionamento com clientes. Para isso, utilizaremos Python com FastAPI, desenvolvendo tanto o back-end quanto o front-end.

Preparando-se para o desenvolvimento

Quais são os requisitos prévios? Um conhecimento básico de Python, pois codificaremos muitas coisas em Python, sem entrar em tópicos avançados. Veremos muitos métodos HTTP, construindo uma API mais orientada ao back-end. Vamos explorar os métodos GET, PUT, POST e DELETE. Utilizaremos HTML, CSS e JS de forma básica, além de programação orientada a objetos em Python, criando classes e classes filhas para garantir um bom uso do que Python oferece.

Para isso, usaremos o próprio Python, o FastAPI, o Uvicorn (um servidor web onde o FastAPI estará hospedado e que executará o código do FastAPI) e o SQLite, para armazenar dados em memória, criando um arquivo local. Podemos armazenar tanto em memória quanto localmente.

Estamos preparados? Vamos construir nossa API. Vamos lá.

Primeiros Passos com FastAPI e Programação Assíncrona - Programação Assíncrona

Discutindo a importância do processamento assíncrono no FastAPI

Hoje vamos discutir por que o processamento assíncrono no FastAPI é tão importante para garantir alto desempenho. Para ilustrar isso, vamos comparar o processamento assíncrono com o síncrono. À primeira vista, pode parecer fácil entender a diferença, mas vamos analisar na prática, no código, o que muda de um processamento síncrono para um assíncrono.

Para isso, vamos utilizar o VSCode. Primeiro, clicamos no ícone que representa uma folha com a esquina dobrada. Ao abrir, temos a lista de arquivos, e, por enquanto, apenas o README, que foi apresentado no último vídeo. Vamos criar um novo arquivo clicando no ícone de "novo arquivo", que é representado por um símbolo de "+", semelhante à folha do Explorer. Esse novo arquivo será chamado script_sincrono.py.

Implementando o processamento síncrono

Neste código, vamos descrever um processamento síncrono, simulando uma leitura de uma base de dados. Para isso, inseriremos uma pausa (sleep) de dois segundos para simular um pouco de demora, pois não queremos implementar funcionalidades adicionais agora, apenas demonstrar como funciona um processo síncrono que demora em comparação com um assíncrono.

Vamos analisar este código. Estamos importando time, que é a biblioteca padrão do Python para trabalhar com tempo. Criamos um novo método chamado fazer_pedido_sincrono, que recebe um id da requisição. Este método imprime uma nova linha para registrar quando a execução está ocorrendo, indicando o início da requisição e seu número. Em seguida, fazemos a pausa (sleep) de dois segundos e, por fim, indicamos que a requisição está pronta.

import time

def fazer_pedido_sincrono(id_pedido):
    print(f"[Sync] Começando pedido {id_pedido}...")
    time.sleep(2) # Tempo em espera
    print(f"[Sync] Pedido {id_pedido} pronto!")

Executando o script síncrono

Mais abaixo, temos um novo método chamado executar_sincrono. Ele imprime uma mensagem no início, indicando o início do modo síncrono. Vamos medir o tempo exato em que o sistema começou a rodar, ou seja, a hora em que este processo síncrono começou. Chamamos o método fazer_pedido_sincrono três vezes, cada uma com um id diferente para diferenciá-las na impressão. Por último, calculamos o tempo final, pegando novamente o tempo atual e subtraindo do tempo inicial, obtendo assim a quantidade de segundos e milissegundos que transcorreram do início ao fim.

def executar_sincrono():
    print("--- INICIANDO MODO SÍNCRONO ---")
    inicio = time.time()

    fazer_pedido_sincrono(1)
    fazer_pedido_sincrono(2)
    fazer_pedido_sincrono(3)

    fim = time.time()
    print(f"--- Tempo total Síncrono: {fim - inicio:.2f} segundos ---\n")

Vamos imprimir novamente e, por último, temos o famoso if __name__ == "__main__" do Python. Vamos executar o processo síncrono. Vamos à parte superior do VSCode, clicar em terminal e criar um novo terminal. Com ele aberto, ao executar ls, veremos que está o arquivo README e o script síncrono. Vamos executar o script síncrono neste momento, então vamos digitar python3 script_sincrono.py. Ele começará a ser executado, e podemos observar que está executando a requisição 1 e se completando, depois começa a executar a requisição 2 e se completa, e depois executa a requisição 3 e se completa. Podemos contar que foram 6 segundos, pois, cada vez que fazemos uma requisição, o código espera 2 segundos. No final, temos que esperar 6 segundos no total, porque fizemos 3 requisições.

python3 script_sincrono.py

Criando o script assíncrono

Agora, vamos criar um novo arquivo. No mesmo botão que criamos antes, vamos criar um arquivo chamado script_assincrono.py. Vamos escrever o mesmo código, mas de forma assíncrona. A primeira diferença que podemos notar é que estamos importando uma nova biblioteca, que é a asyncio, a biblioteca do Python para trabalhar com métodos assíncronos, ou seja, com funções assíncronas. Como vai funcionar a parte assíncrona em Python? Continuamos importando time para fazer operações de medição de tempo, do início ao fim. Vamos ver aqui a diferença do método fazer_pedido_assincrono. A primeira coisa que podemos notar é que os métodos assíncronos têm a palavra-chave reservada async, que indica ao Python que este método pode usar a outra palavra-chave, que é await. Assim, ele pode ficar esperando enquanto se executa. A base continua igual, então temos o print da requisição do id, que vai "dormir" por dois segundos, mas de forma assíncrona, e vai imprimir novamente que a requisição foi concluída.

import asyncio
import time

async def fazer_pedido_assincrono(id_pedido):
    print(f"[Async] Começando pedido {id_pedido}...")
    await asyncio.sleep(2) # Tempo em espera
    print(f"[Async] Pedido {id_pedido} pronto!")

Executando o script assíncrono

Observando o método executar_assincrono, a mesma diferença se aplica: vamos ter async e await. Assim, imprimimos que vai iniciar, calculamos o tempo inicial. A grande diferença é que estamos fazendo as três requisições de forma assíncrona dentro do asyncio.gather. O que isso faz? Ele une essas três requisições, e quando usamos o .gather, o asyncio.gather toma essas três execuções e as inicia em paralelo. Quando usamos asyncio.gather, ele toma essas três operações, essas três chamadas ao método, e as executa de forma concorrente. Pense que estamos olhando para o ponto zero; a partir desse momento, quando for iniciar as três, ele começará a alternar entre elas de forma concorrente, garantindo que serão executadas de forma concorrente.

async def executar_assincrono():
    print("--- INICIANDO MODO ASSÍNCRONO ---")
    inicio = time.time()

    await asyncio.gather(
        fazer_pedido_assincrono(1),
        fazer_pedido_assincrono(2),
        fazer_pedido_assincrono(3),
    )

    fim = time.time()
    print(f"--- Tempo total Assíncrono: {fim - inicio:.2f} segundos ---")

Por último, temos aqui a medição do tempo e outro método que foi alterado no if __name__ == "__main__" para executar isso quando o rodamos diretamente no terminal, que é asyncio.run. O Python padrão não pode usar await se não estiver no loop de eventos, então asyncio.run garante que o código será executado dentro do loop de eventos. Vamos salvar este arquivo, voltar ao nosso terminal, ampliar a tela e fazer o mesmo, mas executando o outro script. Então, python3 script_assincrono.py. A grande diferença é que este já iniciou com 3, então já fez 3 requisições, que foram completadas, e no total levou 2 segundos. Esta é a grande vantagem do FastAPI, que pode garantir alto desempenho, pois tudo no FastAPI é executado de forma assíncrona e concorrente. Isso garante que um código não bloqueará o outro e não precisa depender de que a primeira requisição funcione para que a segunda prossiga no modo síncrono. Estamos obrigados a esperar: quando o método 1 termina, ele chama o método 2, e quando o método 2 termina, ele chama o método 3. Na forma assíncrona, dizemos: "execute estas 3 de forma concorrente e me avise quando terminarem". Assim, só sairá do await quando essas 3 tiverem respondido. Por isso, no total, sempre levará o pior caso. Como todos aqui "dormem" por 2 segundos, o tempo total de espera será de 2 segundos.

python3 script_assincrono.py

Concluindo e introduzindo o próximo tema

No próximo vídeo, vamos ver a diferença entre APIs e Websites.

Primeiros Passos com FastAPI e Programação Assíncrona - Apis vs Websites

Discutindo a diferença entre APIs e sites web

Continuando com o que vimos no último vídeo, vamos discutir sobre APIs e sites web. Qual é a grande diferença entre eles? Para isso, vamos criar um novo arquivo chamado apis-websites.md para descrever um pouco essa diferença.

Existem várias formas de acessar um servidor web. Podemos acessar através de uma API. Como podemos definir o que é uma API? Em inglês, API significa Application Programming Interface (Interface de Programação de Aplicações). Podemos definir uma Interface de Programação de Aplicações como a forma pela qual uma aplicação ou sistema se comunica com outro. Consideramos isso uma interface porque é onde ambos se encontram. Temos uma interface A e uma interface B, e é assim que elas se comunicam.

Definindo e ilustrando o funcionamento de uma API

Para ilustrar, vamos começar com a definição básica de uma API:

API

Como isso funciona? Podemos definir uma API como algo que sempre vai devolver dados puros. Por exemplo, podemos devolver algo em JSON. Isso seria uma resposta OK de uma API que retorna um estado OK:

{"status": "ok"}

Também podemos devolver um XML com o valor de status OK:

<status>ok</status>

Para isso, utilizamos vários padrões, como as APIs REST, nas quais usamos os métodos HTTP. Podemos definir que isso será um GET status para que nos devolva qual é o estado. Pode ser um JSON ou um XML. Isso é o que pode definir uma API:

GET /status

Explorando métodos e contratos de API

Além disso, ao redor dela, teremos a parte de contratos. O GET status sempre vai devolver um atributo status. Mas, e se quisermos enviar um dado para um servidor ou uma aplicação? Podemos usar o POST. Vamos colocar aqui POST cliente, que vai receber um JSON também com o nome do cliente, que poderia ser Raphael, e uma idade de 30 anos:

POST /cliente

O JSON enviado seria:

{"nome": "Raphael", "idade": 30}

Garantimos que o atributo nome sempre será uma string e a idade sempre será um número. Podemos documentar isso e definir esse tipo de interface para os clientes dessa aplicação, para outros consumidores dessa aplicação. Assim, eles saberão que, para criar um novo cliente interno, é necessário enviar um nome que é uma string e uma idade que é um número:

nome = string
idade = number

Ampliando a definição de API e sua comunicação

Podemos definir que uma API é a parte responsável por devolver dados puros. No entanto, não se limita apenas a dados em formatos como JSON, XML ou texto simples. Podemos ter uma API que devolve áudio, imagem, e, no caso de um serviço de streaming, pode devolver um vídeo ou parte dele. A API é sempre a camada que se comunica com outras aplicações.

Para definir o que é uma API, devemos considerar se ela vai se comunicar com outras aplicações, se desejamos que um aplicativo móvel a consuma ou a acesse, ou se outro serviço, como dois back-ends se comunicando, ou até mesmo o próprio front-end, que seria o site, acessando a API.

Relacionando APIs com o front-end e back-end

Falando nisso, temos o site, que é a parte visível, conhecida como front-end. Ele pode devolver páginas HTML completas, exibindo os dados que foram retornados pela API ou o que se espera enviar a uma API. Quando preenchemos um formulário em uma nova rede social, estamos literalmente inserindo nossos dados, e ao clicar em salvar ou enviar, realizamos um POST, uma chamada HTTP ao servidor via API, permitindo que nossos dados sejam salvos. Por isso, podemos acessar a rede social posteriormente. O front-end cria essa camada visual, mostrando o que uma API devolve ou espera, e quando visualizamos publicações na rede social, também estamos chamando uma API que nos devolve uma lista.

Assim, a API devolve algo esperado, previamente acordado entre o back-end e o front-end, entre a API e o site. Podemos afirmar que existem essas duas camadas. Uma API não é apenas via HTTP, podendo usar outros tipos de protocolos, mas é ela quem fornece os dados. Normalmente, o site é quem consome esses dados, consome essas APIs, e até mesmo consome outros sites para gerar um único. Essa é a grande diferença entre uma API e um site.

Introduzindo o uso do FastAPI

Além disso, o FastAPI pode entregar tanto uma API quanto a parte de back-end, que veremos nos próximos vídeos, assim como a parte de front-end. Vamos construir um código HTML que será servido pelo FastAPI. Vamos prosseguir para os próximos vídeos.

Sobre o curso FastAPI e Python: construindo APIs com autenticação, banco de dados e deploy

O curso FastAPI e Python: construindo APIs com autenticação, banco de dados e deploy possui 228 minutos de vídeos, em um total de 49 atividades. Gostou? Conheça nossos outros cursos de Python em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Python acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas