|
| 1 | +# Transmitir dados { #stream-data } |
| 2 | + |
| 3 | +Se você quer transmitir dados que podem ser estruturados como JSON, você deveria [Transmitir JSON Lines](../tutorial/stream-json-lines.md). |
| 4 | + |
| 5 | +Mas se você quer transmitir dados binários puros ou strings, veja como fazer. |
| 6 | + |
| 7 | +/// info | Informação |
| 8 | + |
| 9 | +Adicionado no FastAPI 0.134.0. |
| 10 | + |
| 11 | +/// |
| 12 | + |
| 13 | +## Casos de uso { #use-cases } |
| 14 | + |
| 15 | +Você pode usar isto para transmitir strings puras, por exemplo diretamente da saída de um serviço de AI LLM. |
| 16 | + |
| 17 | +Você também pode usá-lo para transmitir arquivos binários grandes, enviando cada bloco de dados à medida que o lê, sem precisar carregar tudo na memória de uma vez. |
| 18 | + |
| 19 | +Você também pode transmitir vídeo ou áudio desta forma; pode até ser gerado enquanto você processa e envia. |
| 20 | + |
| 21 | +## Um `StreamingResponse` com `yield` { #a-streamingresponse-with-yield } |
| 22 | + |
| 23 | +Se você declarar `response_class=StreamingResponse` na sua função de operação de rota, você pode usar `yield` para enviar cada bloco de dados em sequência. |
| 24 | + |
| 25 | +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} |
| 26 | + |
| 27 | +O FastAPI entregará cada bloco de dados para `StreamingResponse` como está, não tentará convertê-lo para JSON nem nada semelhante. |
| 28 | + |
| 29 | +### Funções de operação de rota não assíncronas { #non-async-path-operation-functions } |
| 30 | + |
| 31 | +Você também pode usar funções `def` normais (sem `async`) e usar `yield` da mesma forma. |
| 32 | + |
| 33 | +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} |
| 34 | + |
| 35 | +### Sem anotação { #no-annotation } |
| 36 | + |
| 37 | +Você não precisa declarar a anotação de tipo de retorno para transmitir dados binários. |
| 38 | + |
| 39 | +Como o FastAPI não tentará converter os dados para JSON com Pydantic nem serializá-los de nenhuma forma, neste caso a anotação de tipo serve apenas para seu editor e ferramentas; ela não será usada pelo FastAPI. |
| 40 | + |
| 41 | +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} |
| 42 | + |
| 43 | +Isso também significa que, com `StreamingResponse`, você tem a liberdade e a responsabilidade de produzir e codificar os bytes exatamente como precisam ser enviados, independentemente das anotações de tipo. 🤓 |
| 44 | + |
| 45 | +### Transmitir bytes { #stream-bytes } |
| 46 | + |
| 47 | +Um dos principais casos de uso é transmitir `bytes` em vez de strings; você pode fazer isso sem problemas. |
| 48 | + |
| 49 | +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} |
| 50 | + |
| 51 | +## Um `PNGStreamingResponse` personalizado { #a-custom-pngstreamingresponse } |
| 52 | + |
| 53 | +Nos exemplos acima, os bytes eram transmitidos, mas a resposta não tinha um cabeçalho `Content-Type`, então o cliente não sabia que tipo de dado estava recebendo. |
| 54 | + |
| 55 | +Você pode criar uma subclasse personalizada de `StreamingResponse` que define o cabeçalho `Content-Type` para o tipo de dado que você está transmitindo. |
| 56 | + |
| 57 | +Por exemplo, você pode criar um `PNGStreamingResponse` que define o cabeçalho `Content-Type` como `image/png` usando o atributo `media_type`: |
| 58 | + |
| 59 | +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} |
| 60 | + |
| 61 | +Em seguida, você pode usar essa nova classe em `response_class=PNGStreamingResponse` na sua função de operação de rota: |
| 62 | + |
| 63 | +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} |
| 64 | + |
| 65 | +### Simular um arquivo { #simulate-a-file } |
| 66 | + |
| 67 | +Neste exemplo, estamos simulando um arquivo com `io.BytesIO`, que é um objeto semelhante a arquivo que vive somente na memória, mas nos permite usar a mesma interface. |
| 68 | + |
| 69 | +Por exemplo, podemos iterar sobre ele para consumir seu conteúdo, como faríamos com um arquivo. |
| 70 | + |
| 71 | +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} |
| 72 | + |
| 73 | +/// note | Detalhes Técnicos |
| 74 | + |
| 75 | +As outras duas variáveis, `image_base64` e `binary_image`, são uma imagem codificada em Base64 e depois convertida para bytes, para então passá-la para `io.BytesIO`. |
| 76 | + |
| 77 | +Apenas para que possa viver no mesmo arquivo deste exemplo e você possa copiar e executar como está. 🥚 |
| 78 | + |
| 79 | +/// |
| 80 | + |
| 81 | +Ao usar um bloco `with`, garantimos que o objeto semelhante a arquivo seja fechado após a função geradora (a função com `yield`) terminar. Ou seja, após terminar de enviar a resposta. |
| 82 | + |
| 83 | +Isso não seria tão importante neste exemplo específico porque é um arquivo falso em memória (com `io.BytesIO`), mas com um arquivo real, seria importante garantir que o arquivo fosse fechado ao final do trabalho. |
| 84 | + |
| 85 | +### Arquivos e async { #files-and-async } |
| 86 | + |
| 87 | +Na maioria dos casos, objetos semelhantes a arquivo não são compatíveis com async e await por padrão. |
| 88 | + |
| 89 | +Por exemplo, eles não têm `await file.read()`, nem `async for chunk in file`. |
| 90 | + |
| 91 | +E, em muitos casos, lê-los seria uma operação bloqueante (que poderia bloquear o loop de eventos), pois são lidos do disco ou da rede. |
| 92 | + |
| 93 | +/// info | Informação |
| 94 | + |
| 95 | +O exemplo acima é, na verdade, uma exceção, porque o objeto `io.BytesIO` já está em memória, então lê-lo não bloqueará nada. |
| 96 | + |
| 97 | +Mas, em muitos casos, ler um arquivo ou um objeto semelhante a arquivo bloquearia. |
| 98 | + |
| 99 | +/// |
| 100 | + |
| 101 | +Para evitar bloquear o loop de eventos, você pode simplesmente declarar a função de operação de rota com `def` normal em vez de `async def`. Assim, o FastAPI a executará em um worker de threadpool, evitando bloquear o loop principal. |
| 102 | + |
| 103 | +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} |
| 104 | + |
| 105 | +/// tip | Dica |
| 106 | + |
| 107 | +Se você precisar chamar código bloqueante de dentro de uma função assíncrona ou uma função assíncrona de dentro de uma função bloqueante, você poderia usar o [Asyncer](https://asyncer.tiangolo.com), uma biblioteca irmã do FastAPI. |
| 108 | + |
| 109 | +/// |
| 110 | + |
| 111 | +### `yield from` { #yield-from } |
| 112 | + |
| 113 | +Quando você está iterando sobre algo, como um objeto semelhante a arquivo, e faz `yield` para cada item, você também pode usar `yield from` para produzir cada item diretamente e pular o loop `for`. |
| 114 | + |
| 115 | +Isso não é particular do FastAPI, é apenas Python, mas é um truque útil para conhecer. 😎 |
| 116 | + |
| 117 | +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} |
0 commit comments