From 5831fffd0ba9a466d2a6bb625612430df7fec13a Mon Sep 17 00:00:00 2001 From: CrazyAnry Date: Wed, 4 Mar 2026 22:08:49 +0700 Subject: [PATCH] Full translation of the stream-data page (this and previous commit - fully working versions, that have been tested locally) --- docs/ru/docs/advanced/stream-data.md | 117 +++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 docs/ru/docs/advanced/stream-data.md diff --git a/docs/ru/docs/advanced/stream-data.md b/docs/ru/docs/advanced/stream-data.md new file mode 100644 index 0000000000..8345424476 --- /dev/null +++ b/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] *}