Python Web框架-FastAPI教程-全局异常处理 作者:马育民 • 2026-05-10 20:12 • 阅读:10001 # 介绍 在国内后端开发中,几乎所有公司都遵循一套固定响应规范: **无论成功还是失败,HTTP 状态码永远返回 200;通过自定义业务码 code 判断请求状态。** 而 FastAPI 默认返回格式杂乱、报错会直接抛出堆栈信息、不方便前端统一处理。 本文记录一套**最简单、最标准、企业通用**的写法: - ✅ 成功统一返回格式 - ✅ 业务错误直接 raise 抛出,不用手写 JSON - ✅ 全局异常捕获,屏蔽后端报错堆栈 - ✅ 完全符合国内前后端交互规范 # 设计思想 ### 1、错误逻辑:抛出异常,统一处理 只要接口**不符合业务条件**,不要 return 错误 json。 直接:`raise HTTPException\(业务码, 错误信息\)` 由全局异常处理器统一封装返回结构。 ### 2、正常逻辑:直接返回数据 业务正常时,调用封装好的成功函数,直接返回标准化数据。 ### 3、国内规范铁律 **HTTP 状态码一律 200,code 控制业务状态。** # 案例 ### 全局HTTPException异常捕获 处理 `HTTPException` 异常 ``` # ------------------------------ # 全局异常处理器:捕获主动抛出的业务异常(HTTPException异常) # ------------------------------ @app.exception_handler(HTTPException) async def http_exception_handler(request, exc: HTTPException): """ 统一处理手动抛出的业务异常 国内规范:HTTP状态码永远200,code为自定义业务码 """ return JSONResponse( status_code=200, content={ "code": exc.status_code, "message": exc.detail, "data": None } ) ``` ### 全局未知异常处理器 处理 非 `HTTPException` 异常 ``` # ------------------------------ # 全局未知异常(非HTTPException异常)处理器:捕获代码bug、崩溃、报错 # ------------------------------ @app.exception_handler(Exception) async def general_exception_handler(request, exc): """服务器未知错误,屏蔽堆栈信息""" return JSONResponse( status_code=200, content={ "code": 500, "message": "服务器内部错误", "data": None } ) ``` ### 完整代码 ```python from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse app = FastAPI() # ------------------------------ # 全局异常处理器:捕获主动抛出的业务异常(HTTPException异常) # ------------------------------ @app.exception_handler(HTTPException) async def http_exception_handler(request, exc: HTTPException): """ 统一处理手动抛出的业务异常 国内规范:HTTP状态码永远200,code为自定义业务码 """ return JSONResponse( status_code=200, content={ "code": exc.status_code, "message": exc.detail, "data": None } ) # ------------------------------ # 全局未知异常(非HTTPException异常)处理器:捕获代码bug、崩溃、报错 # ------------------------------ @app.exception_handler(Exception) async def general_exception_handler(request, exc): """服务器未知错误,屏蔽堆栈信息""" return JSONResponse( status_code=200, content={ "code": 500, "message": "服务器内部错误", "data": None } ) # ------------------------------ # 统一成功返回工具函数 # ------------------------------ def success_response(data=None, message: str = "请求成功"): """成功统一返回格式""" return { "code": 200, "message": message, "data": data } ``` ### 业务接口写法 业务错误:直接抛异常 ```python @app.get("/user/{user_id}") async def get_user(user_id: int): # 不满足条件:直接抛异常,不用写return if user_id <= 0: raise HTTPException(status_code=400, detail="用户ID不合法") # 模拟查询用户 user_info = { "id": user_id, "username": "测试用户", "age": 22 } # 正常返回:调用成功封装函数 return success_response(user_info) ``` ### 最终返回格式 #### 1、成功响应示例 ```Plain { "code": 200, "message": "请求成功", "data": { "id": 10, "username": "测试用户", "age": 22 } } ``` #### 2、业务错误响应示例 ```Plain { "code": 400, "message": "用户ID不合法", "data": null } ``` #### 3、服务器未知错误示例 ```Plain { "code": 500, "message": "服务器内部错误", "data": null } ``` # 为什么要这样写? ### 1、业务代码极度干净 不需要在每个 if 判断里重复写错误 JSON。 不符合条件 → raise;正常逻辑 → return。 ### 2、全站返回格式强制统一 无论谁写接口,格式永远一致,前端无需适配多种结构。 ### 3、后期维护极其方便 如果后期要改返回字段(比如 message 改成 msg),**只改一处**,不用改全部接口。 ### 4、隐藏服务器报错,安全性高 代码崩溃、数据库报错不会暴露堆栈信息,生产环境必备。 ### 5、完全贴合国内开发规范 HTTP 状态码永远为 200,前端不用处理 http 异常拦截,只判断 code。 # 总结 - **不符合业务条件:raise HTTPException**(交给全局处理器) - **正常业务逻辑:return success\_response\(\)**(统一成功格式) - **代码意外崩溃:自动走500异常**(隐藏错误) - **HTTP状态码永远200,code区分业务状态**(国内规范) # 拓展 后续可以在此基础上升级: 1. 自定义业务异常枚举(1001未登录、1002密码错误) 2. 异常自动日志记录 3. 全局请求拦截、token校验 4. 统一分页返回模板 原文出处:http://www.malaoshi.top/show_1GW3HquMfBPO.html