Browse Source

update async.md

pull/14228/head
Rafael de Oliveira Marques 9 months ago
parent
commit
daae0c621a
  1. 147
      docs/pt/docs/async.md

147
docs/pt/docs/async.md

@ -1,10 +1,10 @@
# Concorrência e async / await
# Concorrência e async / await { #concurrency-and-async-await }
Detalhes sobre a sintaxe `async def` para *funções de operação de rota* e alguns conceitos de código assíncrono, concorrência e paralelismo.
## Com pressa?
## Com pressa? { #in-a-hurry }
<abbr title="muito longo; não li"><strong>TL;DR:</strong></abbr>
<abbr title="too long; didn't read – muito longo; não li"><strong>TL;DR:</strong></abbr>
Se você estiver utilizando bibliotecas de terceiros que dizem para você chamar as funções com `await`, como:
@ -12,7 +12,7 @@ Se você estiver utilizando bibliotecas de terceiros que dizem para você chamar
results = await some_library()
```
Então, declare sua *função de operação de rota* com `async def` como:
Então, declare suas *funções de operação de rota* com `async def` como:
```Python hl_lines="2"
@app.get('/')
@ -21,7 +21,7 @@ async def read_results():
return results
```
/// note
/// note | Nota
Você só pode usar `await` dentro de funções criadas com `async def`.
@ -29,7 +29,7 @@ Você só pode usar `await` dentro de funções criadas com `async def`.
---
Se você está usando biblioteca de terceiros que se comunica com alguma coisa (um banco de dados, uma API, sistema de arquivos etc) e não tem suporte para utilizar `await` (esse é atualmente o caso para a maioria das bibliotecas de banco de dados), então declare suas *funções de operação de rota* normalmente, com apenas `def`, como:
Se você está usando uma biblioteca de terceiros que se comunica com alguma coisa (um banco de dados, uma API, o sistema de arquivos etc.) e não tem suporte para utilizar `await` (esse é atualmente o caso para a maioria das bibliotecas de banco de dados), então declare suas *funções de operação de rota* normalmente, com apenas `def`, como:
```Python hl_lines="2"
@app.get('/')
@ -40,7 +40,7 @@ def results():
---
Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`.
Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`, mesmo que você não precise usar `await` dentro dela.
---
@ -54,17 +54,17 @@ De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamen
Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance.
## Detalhes Técnicos
## Detalhes Técnicos { #technical-details }
Versões modernas de Python tem suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**.
Versões modernas de Python têm suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**.
Vamos ver aquela frase por partes na seção abaixo:
Vamos ver aquela frase por partes nas seções abaixo:
* **Código assíncrono**
* **`async` e `await`**
* **Corrotinas**
## Código assíncrono
## Código assíncrono { #asynchronous-code }
Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝.
@ -74,10 +74,10 @@ Então o computador / programa 🤖 irá voltar sempre que tiver uma chance, sej
Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela.
Esse "esperar por algo" normalmente se refere a operações <abbr title="Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por:
Esse "esperar por algo" normalmente se refere a operações <abbr title="Input and Output – Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por:
* dados do cliente para serem enviados através da rede
* dados enviados pelo seu programa serem recebidos pelo clente através da rede
* dados enviados pelo seu programa serem recebidos pelo cliente através da rede
* conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa
* conteúdo que seu programa deu ao sistema para ser escrito no disco
* uma operação em uma API remota
@ -85,7 +85,7 @@ Esse "esperar por algo" normalmente se refere a operações <abbr title="Entrada
* uma solicitação no banco de dados retornar o resultado
* etc.
Quanto o tempo de execução é consumido majoritariamente pela espera de operações <abbr title="Entrada e Saída">I/O</abbr>, essas operações são chamadas operações "limitadas por I/O".
Quanto o tempo de execução é consumido majoritariamente pela espera de operações <abbr title="Input and Output – Entrada e Saída">I/O</abbr>, essas operações são chamadas operações "limitadas por I/O".
Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho.
@ -93,9 +93,9 @@ Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa po
Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar.
### Concorrência e hambúrgueres
### Concorrência e hambúrgueres { #concurrency-and-burgers }
Essa idéia de código **assíncrono** descrita acima é às vezes chamado de **"concorrência"**. Isso é diferente de **"paralelismo"**.
Essa ideia de código **assíncrono** descrita acima é às vezes chamada de **"concorrência"**. Isso é diferente de **"paralelismo"**.
**Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo".
@ -103,31 +103,51 @@ Mas os detalhes entre *concorrência* e *paralelismo* são bem diferentes.
Para ver essa diferença, imagine a seguinte história sobre hambúrgueres:
### Hambúrgueres concorrentes
### Hambúrgueres concorrentes { #concurrent-burgers }
Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔
O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes).
<img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saibam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes).
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
Você paga. 💸
O caixa te entrega seu número de chamada.
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados).
Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨.
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez.
Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa.
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
/// info | Informação
Belas ilustrações de <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
---
Imagine que você seja o computador / programa nessa história.
Imagine que você seja o computador / programa 🤖 nessa história.
Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem.
@ -139,13 +159,13 @@ Contudo, à medida que você se afasta do balcão e senta na mesa, com um númer
Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles.
Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres.
Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres.
Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹.
Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada ⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹.
### Hambúrgueres paralelos
### Hambúrgueres paralelos { #parallel-burgers }
Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos"
Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos".
Você vai com seu _crush_ na lanchonete paralela.
@ -153,29 +173,47 @@ Você fica na fila enquanto vários (vamos dizer 8) caixas que também são cozi
Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido.
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_.
Você paga 💸.
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
O caixa vai para a cozinha.
Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas.
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞
Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro👨‍🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los.
Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro 👨‍🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los.
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
Então seu caixa / cozinheiro 👨‍🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão.
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
Você pega seus hambúrgueres e vai para a mesa com seu _crush_.
Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞
/// info | Informação
Belas ilustrações de <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
---
Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo.
Nesse cenário dos hambúrgueres paralelos, você é um computador / programa 🤖 com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo.
A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro).
@ -183,7 +221,7 @@ Ainda assim, a experiência final não foi a melhor. 😞
---
Essa seria o equivalente paralelo à histório dos hambúrgueres. 🍔
Essa seria o equivalente paralelo à história dos hambúrgueres. 🍔
Para um exemplo "mais real", imagine um banco.
@ -195,7 +233,7 @@ E você tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a ve
Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦.
### Conclusão dos hambúrgueres
### Conclusão dos hambúrgueres { #burger-conclusion }
Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯.
@ -215,7 +253,7 @@ E esse é o mesmo nível de performance que você tem com o **FastAPI**.
E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(tudo graças ao Starlette)</a>.
### Concorrência é melhor que paralelismo?
### Concorrência é melhor que paralelismo? { #is-concurrency-better-than-parallelism }
Não! Essa não é a moral da história.
@ -239,7 +277,7 @@ Mas nesse caso, se você trouxesse os 8 ex-caixas / cozinheiros / agora-faxineir
Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho.
E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbr title="Unidade de Processamento Central">CPU</abbr>. Eles chamam esses problemas de "limitados por CPU".
E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbr title="Central Processing Unit – Unidade Central de Processamento">CPU</abbr>. Eles chamam esses problemas de "limitados por CPU".
---
@ -249,22 +287,20 @@ Por exemplo:
* **Processamento de áudio** ou **imagem**
* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo
* **Aprendizado de Máquina**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo.
* **Deep Learning**: Esse é um subcampo do Aprendizado de Máquina, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos.
* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo.
* **Deep Learning**: Esse é um subcampo do Machine Learning, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos.
### Concorrência + Paralelismo: Web + Machine learning
### Concorrência + Paralelismo: Web + Aprendizado de Máquina { #concurrency-parallelism-web-machine-learning }
Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS).
Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning.
Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina.
Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras).
Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Aprendizado de Máquina (entre muitas outras).
Para ver como alcançar esse paralelismo em produção veja a seção sobre [Deployment](deployment/index.md){.internal-link target=_blank}.
Para ver como alcançar esse paralelismo em produção veja a seção sobre [Implantação](deployment/index.md){.internal-link target=_blank}.
## `async` e `await`
## `async` e `await` { #async-and-await }
Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos.
@ -274,7 +310,7 @@ Quando tem uma operação que exigirá espera antes de dar os resultados e tem s
burgers = await get_burgers(2)
```
A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição).
A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição).
Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`:
@ -306,18 +342,18 @@ burgers = get_burgers(2)
Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* com `async def`, como em:
```Python hl_lines="2 3"
```Python hl_lines="2-3"
@app.get('/burgers')
async def read_burgers():
burgers = await get_burgers(2)
return burgers
```
### Mais detalhes técnicos
### Mais detalhes técnicos { #more-technical-details }
Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`.
Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também.
Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` podem ser chamadas somente dentro de funções definidas com `async def` também.
Então, sobre o ovo e a galinha, como você chama a primeira função async?
@ -325,7 +361,7 @@ Se você estivar trabalhando com **FastAPI** não terá que se preocupar com iss
Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo.
### Escreva seu próprio código assíncrono
### Escreva seu próprio código assíncrono { #write-your-own-async-code }
Starlette (e **FastAPI**) são baseados no <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, o que o torna compatível com ambos o <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> da biblioteca padrão do Python, e o <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
@ -333,10 +369,9 @@ Em particular, você pode usar diretamente o <a href="https://anyio.readthedocs.
E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*).
Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono).
Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **preenchimento automático**, **erros inline**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono).
### Outras formas de código assíncrono
### Outras formas de código assíncrono { #other-forms-of-asynchronous-code }
Esse estilo de usar `async` e `await` é relativamente novo na linguagem.
@ -346,17 +381,17 @@ Essa mesma sintaxe (ou quase a mesma) foi também incluída recentemente em vers
Mas antes disso, controlar código assíncrono era bem mais complexo e difícil.
Nas versões anteriores do Python, você poderia utilizar threads ou <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Mas o código é bem mais complexo de entender, debugar, e pensar sobre.
Nas versões anteriores do Python, você poderia utilizar threads ou <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Mas o código é bem mais complexo de entender, debugar, e pensar sobre.
Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao "inferno do callback".
## Corrotinas
## Corrotinas { #coroutines }
**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela.
Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina".
## Conclusão
## Conclusão { #conclusion }
Vamos ver a mesma frase de cima:
@ -366,9 +401,9 @@ Isso pode fazer mais sentido agora. ✨
Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante.
## Detalhes muito técnicos
## Detalhes muito técnicos { #very-technical-details }
/// warning
/// warning | Atenção
Você pode provavelmente pular isso.
@ -378,23 +413,23 @@ Se você tem certo conhecimento técnico (corrotinas, threads, blocking etc) e e
///
### Funções de operação de rota
### Funções de operação de rota { #path-operation-functions }
Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor).
Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento <abbr title="Input/Output: disco lendo ou escrevendo, comunicações de rede.">IO</abbr>.
Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento <abbr title="Input/Output – Entrada e Saída: leitura ou escrita no disco, comunicações de rede.">I/O</abbr>.
Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior.
### Dependências
### Dependências { #dependencies }
O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo.
### Sub-dependências
### Sub-dependências { #sub-dependencies }
Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas".
### Outras funções de utilidade
### Outras funções de utilidade { #other-utility-functions }
Qualquer outra função de utilidade que você chame diretamente pode ser criada com `def` normal ou `async def` e o FastAPI não irá afetar o modo como você a chama.

Loading…
Cancel
Save