You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI转发流式响应时yield无法实时输出内容的问题排查

FastAPI转发流式响应时yield无法实时输出内容的问题排查

兄弟,你这个问题的核心原因其实很明确:你在异步函数里用了同步的requests库,它会阻塞FastAPI的事件循环,导致你的yield没法实时输出内容,必须等整个请求完成后才会一次性返回所有结果。

咱们来拆解一下:

  • requests.post(..., stream=True)虽然开启了流模式,但它本身是同步IO操作。在FastAPI的异步上下文里,同步IO会卡住整个事件循环,没法及时把拿到的chunk通过yield发出去,只能等整个响应流全部接收完,才会继续执行后续的yield逻辑。
  • 而你看到print(chunk)能实时输出,是因为同步的iter_content确实在逐步拿到数据,但事件循环被阻塞了,FastAPI没法及时把这些yield的chunk推送给客户端。

那怎么解决呢?换成异步HTTP客户端就好了,比如用aiohttp,它是完全异步的,不会阻塞事件循环。修改后的代码大概是这样:

import aiohttp
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse

@app.post('/test')
async def test_api(request: Request):
    async def stream_results():
        # 用aiohttp的异步会话
        async with aiohttp.ClientSession() as session:
            async with session.post("http://127.0.0.1:8000/test_api", json={}) as r:
                # 异步迭代响应内容的chunk
                async for chunk in r.content.iter_chunked(1000):
                    print(chunk)
                    yield chunk

    return StreamingResponse(stream_results(), media_type='application/x-ndjson')

这样修改后,async for会实时拿到每个chunk就立刻yield出去,FastAPI的事件循环也不会被阻塞,客户端就能逐步收到流式响应了。

另外还要注意两个小细节:

  • 确保原始的/test_api端点返回的StreamingResponse没有被中间件缓存,FastAPI默认的中间件一般不会,但如果有自定义中间件的话要检查是否有缓存逻辑。
  • aiohttp的iter_chunked参数可以根据你的需求调整大小,和之前的1000保持一致就没问题。

备注:内容来源于stack exchange,提问作者John Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 14:59:32