Browse Source

Full translation of the stream-data page (this and previous commit - fully working versions, that have been tested locally)

pull/15048/head
CrazyAnry 4 months ago
parent
commit
5831fffd0b
  1. 117
      docs/ru/docs/advanced/stream-data.md

117
docs/ru/docs/advanced/stream-data.md

@ -0,0 +1,117 @@
# Потоковая передача данных { #stream-data }
Если вы хотите передавать поток данных, который можно структурировать как JSON, используйте руководство [Stream JSON Lines](../tutorial/stream-json-lines.md){.internal-link target=_blank}.
Но если вам нужно **передавать чистые бинарные данные** или строки, это можно сделать следующим образом.
/// info
Добавлено в FastAPI 0.134.0.
///
## Варианты использования { #use-cases }
Это может быть полезно, если вы хотите передавать чистые строки, например напрямую из вывода сервиса **AI LLM**.
Также это подходит для передачи **больших бинарных файлов**, когда вы отправляете каждый фрагмент данных по мере чтения, не загружая весь файл в память целиком.
Таким же способом можно передавать **видео** или **аудио**, включая случаи, когда они генерируются на лету во время обработки и отправки.
## `StreamingResponse` с использованием `yield` { #a-streamingresponse-with-yield }
Если в функции-обработчике пути вы объявите `response_class=StreamingResponse`, можно использовать `yield`, чтобы поочерёдно отправлять каждый фрагмент данных.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *}
FastAPI будет передавать каждый фрагмент данных в `StreamingResponse` как есть — без попыток преобразовать его в JSON или выполнить иную сериализацию.
### Неасинхронные функции-обработчики пути { #non-async-path-operation-functions }
Можно также использовать обычные функции `def` (без `async`) и применять `yield` аналогичным образом.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *}
### Без аннотации { #no-annotation }
Для потоковой передачи бинарных данных необязательно объявлять аннотацию возвращаемого типа.
Так как FastAPI не будет пытаться преобразовывать данные в JSON через Pydantic или сериализовать их каким-либо образом, аннотации типов в данном случае нужны только для вашего редактора кода и инструментов — сам FastAPI их использовать не будет.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
Это означает, что при использовании `StreamingResponse` у вас есть **свобода** и одновременно **ответственность** формировать и кодировать байты данных именно так, как требуется для отправки, независимо от аннотаций типов. 🤓
### Передача байтов { #stream-bytes }
Один из основных сценариев — передача объектов `bytes` вместо строк. Это полностью поддерживается.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *}
## Пользовательский `PNGStreamingResponse` { #a-custom-pngstreamingresponse }
В предыдущих примерах передавались байты данных, но HTTP-ответ не содержал HTTP-заголовка `Content-Type`, поэтому клиент не знал, какой тип данных получает.
Можно создать собственный подкласс `StreamingResponse`, который устанавливает HTTP-заголовок `Content-Type` в соответствии с типом передаваемых данных.
Например, можно создать `PNGStreamingResponse`, задав атрибут `media_type` со значением `image/png`:
{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *}
Затем этот класс можно использовать в параметре `response_class=PNGStreamingResponse` в функции-обработчике пути:
{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *}
### Имитация файла { #simulate-a-file }
В этом примере используется `io.BytesIO` — файловоподобный объект, который существует только в памяти, но предоставляет тот же интерфейс.
Например, его можно итерировать для чтения содержимого так же, как обычный файл.
{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *}
/// note | Технические детали
Две другие переменные — `image_base64` и `binary_image` — содержат изображение, закодированное в Base64, затем преобразованное в байты и переданное в `io.BytesIO`.
Это сделано только для того, чтобы пример находился в одном файле и его можно было скопировать и запустить как есть. 🥚
///
Используя блок `with`, мы гарантируем, что файловоподобный объект будет закрыт после завершения генераторной функции (функции с `yield`), то есть после отправки HTTP-ответа.
В данном примере это не критично, так как используется объект `io.BytesIO`, находящийся в памяти. Но при работе с реальным файлом важно убедиться, что он закрывается после завершения работы.
### Файлы и async { #files-and-async }
В большинстве случаев файловоподобные объекты по умолчанию не совместимы с `async` и `await`.
Например, у них нет `await file.read()` или `async for chunk in file`.
Кроме того, чтение может быть блокирующей операцией (например, при чтении с диска или из сети), что способно заблокировать цикл событий.
/// info
Пример выше является исключением, так как `io.BytesIO` уже находится в памяти, и его чтение не блокирует выполнение.
Однако в большинстве случаев чтение файла или файловоподобного объекта будет блокирующим.
///
Чтобы избежать блокировки цикла событий, можно объявить функцию-обработчик пути как обычную `def`, а не `async def`. В этом случае FastAPI выполнит её в воркер-процессе из пула потоков, чтобы не блокировать основной цикл.
{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *}
/// tip
Если вам нужно вызвать блокирующий код из асинхронной функции или асинхронную функцию из блокирующей, можно использовать библиотеку Asyncer — сопутствующую библиотеку для FastAPI.
///
### `yield from` { #yield-from }
Если вы итерируетесь по объекту (например, файловоподобному) и вызываете `yield` для каждого элемента, можно использовать `yield from`, чтобы напрямую передавать элементы без явного цикла `for`.
Это относится не только к FastAPI, а к Python в целом, но приём полезный. 😎
{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *}
Loading…
Cancel
Save