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

如何正确处理FastAPI中异步迭代器__aiter__方法抛出的异常

问题根源

你的代码里,__aiter__方法的异常无法被路由中的try-except捕获,是因为StreamingResponse返回时并没有执行__aiter__里的逻辑——只有当客户端开始接收流数据时,异步迭代器的代码才会被触发。这时候路由的响应已经发送(状态码200),后续抛出的异常只能导致连接中断,无法修改已发送的响应状态。

解决方案

根据错误发生的阶段,有两种针对性的处理方式:

1. 处理流迭代过程中的异常(中途出错)

如果错误是在OpenAI API流式返回的过程中发生的,最合理的方式是将错误信息以流的形式发送给前端,而非中断连接。这样前端可以接收错误提示并做对应处理。

# 自定义异常类
class StreamGeneratorError(Exception):
    def __init__(self, message: str):
        self.message = message

class StreamGenerator:
    def __init__(self, prompt: str):
        self.prompt = prompt

    async def __aiter__(self):
        try:
            # 调用OpenAI流式API示例
            stream = await openai.ChatCompletion.acreate(
                model="gpt-3.5-turbo",
                messages=[{"role": "user", "content": self.prompt}],
                stream=True
            )
            async for chunk in stream:
                content = chunk.choices[0].delta.get("content", "")
                if content:
                    yield f"data: {content}\n\n"
        except Exception as e:
            # 以SSE格式发送错误信息
            yield f"data: error: {str(e)}\n\n"
            # 发送流结束信号
            yield "data: [DONE]\n\n"

@router.post("/v1/chat-with-ai")
async def chat_gpt_api_view(body: UserPrompt) -> StreamingResponse:
    stream_gen_instance = StreamGenerator(body.prompt)
    return StreamingResponse(stream_gen_instance, media_type='text/event-stream')

2. 处理初始化阶段的异常(前置错误)

如果错误是在创建流之前发生的(比如参数验证失败、API密钥错误),可以将初始化逻辑移到路由中,提前捕获异常并返回标准错误响应。

class StreamGenerator:
    def __init__(self, openai_stream):
        self.openai_stream = openai_stream

    async def __aiter__(self):
        async for chunk in self.openai_stream:
            content = chunk.choices[0].delta.get("content", "")
            if content:
                yield f"data: {content}\n\n"

@router.post("/v1/chat-with-ai")
async def chat_gpt_api_view(body: UserPrompt):
    try:
        # 提前执行OpenAI API初始化,出错直接抛出异常
        stream = await openai.ChatCompletion.acreate(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": body.prompt}],
            stream=True
        )
        stream_gen_instance = StreamGenerator(stream)
        return StreamingResponse(stream_gen_instance, media_type='text/event-stream')
    except Exception as e:
        raise StreamGeneratorError(f"Failed to start stream: {str(e)}") from e

# 全局异常处理器,统一返回错误格式
@router.exception_handler(StreamGeneratorError)
async def stream_error_handler(request: Request, exc: StreamGeneratorError):
    return JSONResponse(
        status_code=500,
        content={"detail": exc.message}
    )
注意事项
  • 流中途的错误无法修改已发送的200状态码,只能通过流内容传递错误信息
  • 初始化阶段的错误可以提前拦截,返回自定义状态码(如400、500)和响应体

内容的提问来源于stack exchange,提问作者alfik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:07:55