在 FastAPI 中全局捕获 \`Exception\`

新手上路,请多包涵

我试图在全球范围内捕获未处理的异常。所以在 main.py 文件的某处,我有以下内容:

 @app.exception_handler(Exception)
async def exception_callback(request: Request, exc: Exception):
  logger.error(exc.detail)

但是上面的方法永远不会执行。但是,如果我编写一个自定义异常并尝试捕获它(如下所示),它就可以正常工作。

 class MyException(Exception):
  #some code

@app.exception_handler(MyException)
async def exception_callback(request: Request, exc: MyException):
  logger.error(exc.detail)

我已经完成了 Catch exception type of Exception 和 process body request #575 。但是这个错误谈论访问请求正文。看到这个bug,感觉应该可以catch Exception 。我使用的 FastAPI 版本是: fastapi>=0.52.0

提前致谢 :)


更新

有多种答案,在此感谢所有读者和作者。我在我的应用程序中重新访问了这个解决方案。现在我看到我需要设置 debug=False ,默认它是 False ,但我把它设置为 True

 server = FastAPI(
    title=app_settings.PROJECT_NAME,
    version=app_settings.VERSION,
)

当@iedmrc 评论@Kavindu Dodanduwa 给出的答案时,我似乎错过了它。

原文由 Ajeet Singh 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

如果您想捕获所有未处理的异常(内部服务器错误),有一种非常简单的方法可以做到。 文档

from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import Response

app = FastAPI()

async def catch_exceptions_middleware(request: Request, call_next):
    try:
        return await call_next(request)
    except Exception:
        # you probably want some kind of logging here
        return Response("Internal server error", status_code=500)

app.middleware('http')(catch_exceptions_middleware)

确保将此中间件放在其他一切之前。

原文由 AndreFeijo 发布,翻译遵循 CC BY-SA 4.0 许可协议

添加自定义 APIRoute 也可用于处理全局异常。这种方法的优点是,如果从自定义路由中引发了 http 异常,它将由 Starlette 的错误处理程序默认处理:

 from typing import Callable

from fastapi import Request, Response, HTTPException, APIRouter, FastAPI
from fastapi.routing import APIRoute
from .logging import logger

class RouteErrorHandler(APIRoute):
    """Custom APIRoute that handles application errors and exceptions"""

    def get_route_handler(self) -> Callable:
        original_route_handler = super().get_route_handler()

        async def custom_route_handler(request: Request) -> Response:
            try:
                return await original_route_handler(request)
            except Exception as ex:
                if isinstance(ex, HTTPException):
                    raise ex
                logger.exception("uncaught error")
                # wrap error into pretty 500 exception
                raise HTTPException(status_code=500, detail=str(ex))

        return custom_route_handler

router = APIRouter(route_class=RouteErrorHandler)

app = FastAPI()
app.include_router(router)

使用 fastapi==0.68.1 为我工作。

有关自定义路线的更多信息: https ://fastapi.tiangolo.com/advanced/custom-request-and-route/

原文由 madox2 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进