Quando se trata de construir aplicações web eficientes e escaláveis, a programação assíncrona é um recurso indispensável, especialmente quando lidamos com operações de I/O que exigem tempo, como acessos a banco de dados, chamadas de API e operações de rede. Abaixo, exploraremos como podemos melhorar o desempenho da nossa aplicação utilizando FastAPI, considerando a implementação de funções assíncronas para tarefas concorrentes.
Primeiramente, ao utilizar FastAPI, a capacidade de executar funções assíncronas de maneira eficiente pode ser vista no uso de bibliotecas como asyncio, que permite que múltiplas tarefas sejam executadas ao mesmo tempo, sem bloquear o processo principal. Isso é de especial importância em operações de rede ou em transações de banco de dados, que muitas vezes podem ser lentas devido à latência. O benefício imediato do uso de asyncio e funções assíncronas é a resposta mais rápida da aplicação, já que o servidor pode processar múltiplas requisições enquanto aguarda respostas externas.
No exemplo abaixo, demonstramos como iniciar um servidor FastAPI em um processo separado, permitindo que ele seja executado em segundo plano enquanto outras operações acontecem de forma assíncrona. Usamos o decorador @contextmanager para garantir que o servidor seja gerenciado corretamente, iniciando e finalizando o processo de maneira controlada.
Ao definir essa função, garantimos que o servidor seja iniciado e terminado corretamente, permitindo que o código assíncrono de requisições se concentre na execução de múltiplas chamadas para endpoints. Isso é possível utilizando a função AsyncClient do httpx, que permite a realização de várias requisições concorrentes:
Em seguida, podemos organizar essas chamadas em uma função principal, onde realizamos n requisições para diferentes endpoints (sincronos e assíncronos) e calculamos o tempo necessário para atender a todas as requisições:
Ao executar a função main com o número padrão de requisições (10), podemos perceber que o tempo para ambos os endpoints (síncrono e assíncrono) é quase o mesmo. Contudo, quando aumentamos a quantidade de requisições, como para 100, a diferença começa a se tornar visível:
Aqui, o uso de programação assíncrona para realizar múltiplas requisições simultâneas resulta em um tempo significativamente menor para o endpoint assíncrono em comparação com o síncrono. Isso ilustra como operações assíncronas podem ser mais eficazes quando lidamos com tarefas que envolvem espera, como chamadas a bancos de dados ou APIs externas.
Entretanto, nem todas as operações se beneficiam da programação assíncrona. É importante entender que as operações assíncronas são mais vantajosas para tarefas de I/O e que o processamento intensivo de CPU (como operações de cálculos complexos) pode não ter um ganho significativo com a assíncronicidade. Além disso, ao integrar operações assíncronas em sua aplicação, é necessário tomar certos cuidados para garantir a integridade e a performance da aplicação.
Quando se trata de bancos de dados, por exemplo, ao implementar operações CRUD assíncronas em FastAPI, o SQLAlchemy com o módulo asyncio pode ser utilizado para transformar funções síncronas em assíncronas. De forma semelhante, para bancos NoSQL como MongoDB, o pacote motor oferece suporte assíncrono, permitindo que a aplicação se mantenha ágil, mesmo durante operações demoradas.
A programação assíncrona também exige que tenhamos uma gestão cuidadosa de transações e sessões, pois as mudanças de estado podem ser feitas de forma concorrente, o que pode causar inconsistências se não forem gerenciadas corretamente. O uso de gerenciadores de contexto, como async with, ajuda a garantir que as transações sejam iniciadas e finalizadas de maneira adequada, preservando a integridade dos dados.
Além disso, um dos desafios da programação assíncrona é o tratamento de erros. A simultaneidade de múltiplas tarefas torna o manuseio de exceções mais complexo, sendo necessário utilizar blocos try-except para capturar e lidar com falhas que possam surgir durante a execução das tarefas assíncronas.
Outro ponto importante é a realização de testes. A execução de testes assíncronos exige que o framework de testes seja compatível com a programação assíncrona, utilizando async e await para garantir que o código seja testado corretamente.
A adoção da programação assíncrona, portanto, não se resume apenas à escrita do código com async e await, mas envolve uma série de boas práticas para garantir que a aplicação se beneficie de um desempenho superior, enquanto mantém a robustez, a segurança e a integridade. Com a combinação adequada de funções assíncronas, tratamento de erros, testes e gestão de transações, podemos construir sistemas que respondem de forma eficiente, mesmo sob alta carga de trabalho.
Como Testar e Depurar Endpoints de API com FastAPI
A criação de endpoints eficazes é apenas o primeiro passo na construção de uma aplicação robusta. A verdadeira força de um sistema vem da garantia de que ele funciona corretamente em diferentes cenários. Este processo exige uma combinação de boas práticas de desenvolvimento e uma abordagem rigorosa de testes e depuração. Quando usamos o FastAPI, uma das ferramentas mais poderosas para a construção de APIs rápidas e eficientes, entender como configurar e testar adequadamente os endpoints pode ser a chave para garantir o sucesso do projeto. Vamos explorar como fazer isso de maneira eficiente.
Primeiramente, devemos criar um corpo de solicitação adequado para nossos endpoints. Para isso, o Pydantic é utilizado para modelar as estruturas de dados esperadas. No exemplo a seguir, criamos uma classe ItemSchema que define as propriedades necessárias para um item:
Com essa definição, podemos construir um endpoint para adicionar um item. Esse endpoint será responsável por receber dados, armazená-los em um banco de dados e retornar o ID do item. Aqui está um exemplo de como implementá-lo:
Esse endpoint garante que, quando um item for adicionado à base de dados, seu ID será retornado como resposta. Caso o ID do item não corresponda a nenhum registro na base de dados, retornaremos um erro 404. O próximo passo é criar o endpoint para recuperar um item baseado em seu ID, utilizando uma consulta simples ao banco de dados:
Aqui, o FastAPI irá buscar o item no banco de dados, e caso ele não seja encontrado, um erro 404 será retornado.
Agora que os endpoints para adição e recuperação de itens estão prontos, o próximo passo é realizar testes adequados. Para testar essas funções, precisamos garantir que o banco de dados de teste seja configurado corretamente. Para isso, uma boa prática é usar um banco de dados SQLite em memória, o que permite que os testes sejam rápidos e não afetem a base de dados de produção.
Para configurar o banco de dados de teste, seguimos alguns passos. Primeiro, criamos uma instância do banco de dados em memória:
Em seguida, definimos uma fábrica de sessões de banco de dados dedicada aos testes:
Com isso, podemos criar um fixture de teste que utilizará essa sessão de teste:
Além disso, devemos adaptar o test_client para usar essa nova sessão de banco de dados, substituindo a sessão padrão pela sessão de teste:
Agora, podemos escrever os testes para garantir que nossos endpoints estão funcionando corretamente. O objetivo é garantir que, ao adicionar um item por meio do endpoint POST /item, ele seja criado corretamente no banco de dados e possa ser recuperado posteriormente pelo endpoint GET /item/{item_id}:
Esse teste simula a interação completa com a API: primeiro tenta-se recuperar um item que não existe (esperando um erro 404), depois cria-se um novo item e verifica-se se ele foi armazenado corretamente no banco de dados, e, por fim, a consulta do item é realizada para garantir que a resposta esteja correta.
Além disso, é importante garantir que a cobertura dos testes seja alta, o que pode ser feito utilizando ferramentas como o pytest-cov. Com isso, podemos garantir que todas as partes do código estão sendo testadas, inclusive os endpoints da API. A aplicação de marcadores no pytest também facilita a execução de grupos de testes específicos, como por exemplo, os testes de integração:
Ao utilizar marcadores, podemos agrupar os testes conforme suas funcionalidades, tornando o processo de execução e manutenção dos testes mais eficiente.
É fundamental entender que testes não são apenas uma forma de verificar se a aplicação está funcionando corretamente, mas também de garantir que, ao modificar ou adicionar novos recursos, o comportamento da aplicação continue consistente. Além disso, ao realizar testes unitários e de integração, conseguimos identificar pontos de falha de forma antecipada, permitindo uma resposta rápida e uma aplicação mais robusta.
Como Integrar o FastAPI com o gRPC: Um Guia Completo para Construir um Gateway REST-gRPC
Ao integrar o FastAPI com o gRPC, podemos criar uma aplicação que combine as vantagens do gRPC para comunicação eficiente com a facilidade de construção de APIs RESTful oferecida pelo FastAPI. No exemplo a seguir, vamos explorar como construir uma aplicação simples de gateway entre FastAPI e gRPC.
O primeiro passo é configurar o ambiente. Para isso, você deve instalar as bibliotecas necessárias, incluindo o fastapi, uvicorn, grpcio e grpcio-tools. Uma maneira prática de garantir que todas as dependências sejam instaladas é usar um arquivo requirements.txt, ou você pode instalar os pacotes diretamente com o seguinte comando:
Com o ambiente pronto, podemos começar a construir o servidor gRPC básico. O servidor gRPC que vamos criar terá um método que recebe uma mensagem do cliente e envia uma resposta de volta. Para isso, precisamos primeiro definir o serviço e as mensagens no arquivo .proto.
-
Criação do Arquivo
.proto: O primeiro passo é criar um arquivo chamadogrpcserver.protono diretório raiz do projeto. Nele, definimos o serviçoGrpcServere os tipos de mensagem que nosso serviço utilizará. Exemplo de definição do serviço e das mensagens:
A partir desse arquivo .proto, podemos gerar o código Python necessário para implementar o servidor e o cliente gRPC usando o compilador protoc. Execute o seguinte comando:
Esse comando gerará dois arquivos: grpcserver_pb2_grpc.py (que contém a classe para construir o servidor) e grpcserver_pb2.py (que define as mensagens Message e MessageResponse).
-
Implementação do Servidor gRPC: Agora, vamos criar o servidor gRPC. Para isso, criamos o arquivo
grpc_server.pye implementamos a classeService, que vai herdar deGrpcServerServicere implementar o métodoGetServerResponse. O código abaixo define o servidor que escuta requisições e envia respostas para o cliente:
Com o servidor definido, o próximo passo é configurá-lo para rodar na porta 50051. Adicionamos o seguinte código:
Com isso, você tem um servidor gRPC simples que pode ser iniciado com o comando:
Se tudo estiver configurado corretamente, você verá a mensagem de log INFO:root:Starting server on port 50051 no terminal.
-
Criação do Gateway FastAPI: Agora, vamos criar o gateway REST utilizando o FastAPI. Esse gateway será responsável por receber as requisições HTTP e redirecioná-las para o servidor gRPC. Primeiramente, criamos o diretório
appcom o arquivomain.py, onde definimos a aplicação FastAPI.
No arquivo main.py, começamos importando o FastAPI e configurando o servidor:
Em seguida, criamos um modelo de resposta com o Pydantic para refletir a estrutura do MessageResponse do gRPC:
Agora, configuramos a comunicação com o servidor gRPC. Para isso, utilizamos o canal grpc.aio.insecure_channel:
E finalmente, criamos o endpoint /grpc, que recebe uma mensagem e envia uma requisição ao servidor gRPC, retornando a resposta do servidor para o cliente HTTP:
Para rodar a aplicação FastAPI, basta executar o seguinte comando:
Agora, você pode acessar a documentação interativa da API em http://localhost:8000/docs e testar a chamada ao endpoint /grpc. Quando a requisição for realizada, você verá o log no terminal do servidor gRPC com a mensagem recebida.
É importante destacar que, além de chamadas simples como a do tipo Unary RPC (um único envio e resposta), o gRPC oferece suporte a outras formas de comunicação, como streaming de mensagens de/para o servidor ou comunicação bidirecional. Esses tipos de RPC oferecem soluções poderosas para cenários que exigem maior flexibilidade na comunicação.
Embora o processo de integração do FastAPI com o gRPC seja relativamente simples, compreender as diferenças entre os tipos de RPC e saber quando utilizá-los é crucial para tirar o máximo proveito do gRPC.
Como integrar FastAPI com outras bibliotecas Python para criar endpoints GraphQL e ML
Ao trabalhar com FastAPI, muitas vezes é necessário integrar a framework com outras bibliotecas Python, seja para acessar bases de dados ou utilizar modelos de Machine Learning (ML). Neste contexto, exploraremos como integrar o FastAPI com GraphQL para criar endpoints dinâmicos de consulta de dados, bem como como usar modelos de ML com a biblioteca Joblib para criar uma aplicação de diagnóstico inteligente.
A primeira etapa consiste em instalar as dependências necessárias para que o FastAPI e o GraphQL funcionem corretamente. Para isso, podemos usar o arquivo requirements.txt ou o comando pip install fastapi uvicorn strawberry-graphql[fastapi] diretamente no terminal. Uma vez que o ambiente esteja pronto, podemos começar a construir as funcionalidades.
Em primeiro lugar, criamos um módulo database.py que simula uma base de dados simples com uma lista de usuários. Aqui, definimos a classe User com atributos como id, username, phone_number e country usando o BaseModel da biblioteca Pydantic. Este modelo serve para estruturar os dados dos usuários e facilitar a integração com o GraphQL, que, por sua vez, exigirá uma estrutura de dados definida.
Em seguida, criamos o arquivo graphql_utils.py, onde configuramos o GraphQL. Começamos definindo um modelo User usando a biblioteca Strawberry, que facilita a criação de tipos e consultas GraphQL em Python. O modelo User incluirá os mesmos campos presentes na base de dados, garantindo consistência na consulta dos dados. A seguir, implementamos a query que receberá o parâmetro country e retornará uma lista de usuários de determinado país.
A integração entre FastAPI e GraphQL se dá por meio do GraphQLRouter da biblioteca strawberry.fastapi. Criamos o schema GraphQL e, em seguida, adicionamos o roteador ao objeto FastAPI no arquivo main.py. Através desse processo, podemos facilmente criar um endpoint em FastAPI que manipula solicitações GraphQL na rota /graphql. O endpoint se torna interativo ao ser acessado no navegador, permitindo ao desenvolvedor realizar consultas diretamente pela interface gráfica, simplificando o processo de interação com os dados.
Uma vez que o servidor FastAPI esteja rodando com o comando uvicorn main:app, podemos testar a consulta GraphQL diretamente pela interface do navegador. Por exemplo, a consulta para obter os usuários de um determinado país, como os dos Estados Unidos (country: "USA"), resultará em um retorno como:
Esse modelo de integração entre REST e GraphQL abre vastas possibilidades para ampliar a flexibilidade nas consultas e modificações de dados, especialmente em aplicações que envolvem grandes volumes de informações.
Além disso, em cenários mais complexos, podemos combinar a utilização de endpoints RESTful com GraphQL, oferecendo ao usuário uma experiência mais dinâmica na consulta e manipulação de dados. Por exemplo, enquanto REST pode ser utilizado para operações CRUD (criar, ler, atualizar, excluir) no banco de dados, o GraphQL é ideal para obter dados específicos de forma otimizada, sem a necessidade de múltiplas requisições.
Agora, exploraremos como a mesma estrutura do FastAPI pode ser aplicada para integrar modelos de Machine Learning. O Joblib, uma biblioteca popular para serialização de modelos, pode ser usado para carregar e salvar modelos treinados, como o modelo de previsão de doenças desenvolvido com scikit-learn. FastAPI facilita o uso de modelos ML em produção, permitindo criar APIs que podem ser acessadas remotamente para realizar previsões.
Ao desenvolver uma aplicação como um "médico inteligente" que realiza diagnósticos baseados em sintomas, é possível combinar o uso de ML com uma API construída em FastAPI. Para isso, começamos configurando o ambiente com o Joblib, além de instalar as dependências necessárias como scikit-learn e huggingface_hub, que nos permite baixar modelos treinados diretamente do Hugging Face.
Ao carregar o modelo de predição de doenças utilizando a função hf_hub_download do huggingface_hub, podemos implementá-lo no FastAPI com a ajuda do recurso lifespan. Esse recurso gerencia o ciclo de vida do servidor, garantindo que o modelo seja carregado ao iniciar o servidor e descarregado ao final, economizando recursos e melhorando a performance da aplicação.
No código de exemplo, o modelo é carregado na memória ao iniciar a aplicação FastAPI, e um dicionário ml_model mantém o modelo carregado disponível para todas as requisições. A API recebe os sintomas do paciente, realiza a previsão usando o modelo carregado e retorna o diagnóstico, simplificando o processo de análise. O endpoint da API pode ser configurado para receber os sintomas do paciente e retornar o diagnóstico predito pelo modelo ML.
Ao integrar essas ferramentas, o desenvolvimento de uma aplicação de ML robusta e eficiente torna-se mais acessível. A combinação de FastAPI com GraphQL e ML possibilita criar soluções ágeis, escaláveis e facilmente testáveis, aumentando a produtividade e a inovação no desenvolvimento de software.
O que deve ser considerado além do que foi descrito:
Embora o processo descrito seja relativamente simples, existem diversos aspectos que devem ser levados em consideração ao integrar FastAPI com outras bibliotecas. Primeiramente, a escalabilidade e a segurança devem ser analisadas em projetos de maior porte. Em aplicativos de produção, é essencial garantir que as consultas GraphQL e os modelos de ML sejam otimizados para lidar com grandes volumes de dados de maneira eficiente. Além disso, a implementação de autenticação e autorização adequadas pode ser necessária para proteger os dados sensíveis, especialmente em cenários envolvendo informações médicas ou pessoais. A documentação também é crucial, tanto para o uso da API quanto para o treinamento de modelos de ML, garantindo que a equipe de desenvolvimento consiga entender e utilizar o sistema corretamente.
Como a Estética Pós-Digital é Definida pelos Geradores de Imagens com IA: Análise do Caso DALL·E e Midjourney
O que é o Movimento Browniano Fracionário e suas Implicações no Estudo de Processos Estocásticos?
Como Comunicar Conceitos Complexos de Forma Clara e Impactante

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский