我使用FastApi进行开发,并希望在发生错误时在响应中包含回溯信息;
为此,我在exception_handler.py
中定义了异常处理程序:
from fastapi.responses import JSONResponse
from fastapi import status
from fastapi import FastAPI, Request
from traceback import format_exc, print_exc
def general_exception_handler(req: Request, exc: Exception):
'''
Exception handler for unspecified exceptions
'''
tracback_msg = format_exc()
return JSONResponse(
{
"code": status.HTTP_500_INTERNAL_SERVER_ERROR,
"message": f"error info: {tracback_msg}",
# "message": f"error info: {str(exc)}",
"data": "",
},
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
并将这些处理程序附加到server.py
中的fastappi应用程序实例:
server.py
是我创建应用程序实例并附加额外功能的地方,如中间件或异常处理程序。
from core import router # api routers are defined in router.py
from fastapi import FastAPI
from core.exception_handler import general_exception_handler
app = FastAPI(
debug=False,
docs_url=None,
redoc_url=None
)
# attach exception handler to app instance
app.add_exception_handler(Exception, general_exception_handler)
# include routers to app intance
app.include_router(router.router)
问题是,当引发异常时,format_exc()
返回的回溯消息是None
;
但是当我像注释代码一样使用str(exc)
时,我正确地获得了异常信息,但当然没有回溯信息。
它将不起作用,因为异常处理程序将异常作为参数接收,而不是捕获异常本身,这意味着在这种情况下没有堆栈跟踪。
如果你想要堆栈跟踪,你应该创建一个中间件或自定义API路由器,它将实际捕获异常并以你想要的方式返回消息。我通常更喜欢使用自定义API路由,而不是使用中间件,因为它更明确,给你更多的灵活性。
你可以这样写
class MyRoute(APIRoute):
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 exc:
tracback_msg = format_exc()
# your return goes here
return custom_route_handler
然后重写fastapi
中的默认路由处理程序app = FastAPI()
app.router.route_class = MyRoute
它应该给你想要的
总是有format_exception,它接受一个显式的异常参数,而不是从sys.exc_info()
中获取当前的异常。