Fastapi.StreamingResponse: OSError: неполный кадрPython

Программы на Python
Ответить
Anonymous
 Fastapi.StreamingResponse: OSError: неполный кадр

Сообщение Anonymous »

Я пишу сервис FastAPI. Я получил архив .zstd от S3. Мне нужно вернуть распакованные данные json из архива. Я прочитал о fastapi.StreamingResponse
Мой код
import os
import cramjam

from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, File, Body, Path
from fastapi.responses import JSONResponse, StreamingResponse

def iter_decompressed_from_s3(s3_response: Dict, chunk_size: int = 1024 * 1024):
body = s3_response["Body"]
decompressor = cramjam.zstd.Decompressor()

try:
while True:
chunk = body.read(chunk_size)
if not chunk:
break
out = decompressor.decompress(chunk)
if out:
yield bytes(out)
tail = decompressor.flush()
if tail:
yield bytes(tail)
finally:
body.close()

@app.get("/{s3_path:path}")
async def get_file_content(s3_path: str, request: Request):
return StreamingResponse(
iter_decompressed_from_s3(s3_response=response), # ← вот твой "pip"!
media_type="application/octet-stream",
headers={
"Content-Disposition": f'attachment; filename="{s3_path}"',
"Cache-Control": "no-cache",
}
)

У меня ошибка
Traceback (most recent call last):
| File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 259, in __call__
| await wrap(partial(self.listen_for_disconnect, receive))
| File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 255, in wrap
| await func()
| File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 232, in listen_for_disconnect
| message = await receive()
| File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 531, in receive
| await self.message_event.wait()
| File "/usr/local/lib/python3.10/asyncio/locks.py", line 214, in wait
| await fut
| asyncio.exceptions.CancelledError: Cancelled by cancel scope 7efc4ae2dc90

+ Exception Group Traceback (most recent call last):
| | File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
| | result = await app( # type: ignore[func-returns-value]
| | File "/usr/local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
| | return await self.app(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__
| | await super().__call__(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/applications.py", line 113, in __call__
| | await self.middleware_stack(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 187, in __call__
| | raise exc
| | File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 165, in __call__
| | await self.app(scope, receive, _send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
| | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| | raise exc
| | File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
| | await app(scope, receive, sender)
| | File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 715, in __call__
| | await self.middleware_stack(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 735, in app
| | await route.handle(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 288, in handle
| | await self.app(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 76, in app
| | await wrap_app_handling_exceptions(app, request)(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| | raise exc
| | File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
| | await app(scope, receive, sender)
| | File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 74, in app
| | await response(scope, receive, send)
| | File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 252, in __call__
| | async with anyio.create_task_group() as task_group:
| | File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| | raise BaseExceptionGroup(
| | exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
| +-+---------------- 1 ----------------
| | Traceback (most recent call last):
| | File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 255, in wrap
| | await func()
| | File "/usr/local/lib/python3.10/site-packages/starlette/responses.py", line 244, in stream_response
| | async for chunk in self.body_iterator:
| | File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py", line 62, in iterate_in_threadpool
| | yield await anyio.to_thread.run_sync(_next, as_iterator)
| | File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync
| | return await get_async_backend().run_sync_in_worker_thread(
| | File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2461, in run_sync_in_worker_thread
| | return await future
| | File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 962, in run
| | result = context.run(func, *args)
| | File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py", line 51, in _next
| | return next(iterator)
| | File "/app/app/api/v1/geodata.py", line 34, in iter_decompressed_from_s3
| | out = decompressor.decompress(chunk)
| | OSError: incomplete frame


Подробнее здесь: https://stackoverflow.com/questions/798 ... lete-frame
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»