异常处理
异常处理
框架内建统一异常捕获机制,开发者只需抛出业务异常,框架将自动格式化响应。
核心特性
- 统一异常捕获:框架自动捕获并格式化所有异常响应
- 多种异常类型:提供丰富的内置异常类,覆盖常见业务场景
- 国际化支持:异常消息支持多语言国际化
- 详细错误信息:支持自定义错误消息和错误码
- 易于扩展:支持自定义异常类型,满足特殊业务需求
功能概览
功能特性 | 描述 | 优势 |
---|---|---|
统一异常处理 | 框架自动捕获并格式化异常 | 简化错误处理逻辑,保证响应格式一致性 |
内置异常类型 | 提供常用的异常类型 | 快速开发,减少重复代码 |
自定义异常 | 支持继承和扩展异常类 | 满足特殊业务需求 |
国际化集成 | 异常消息支持多语言 | 提升用户体验,支持全球化应用 |
错误码管理 | 支持自定义错误码 | 便于客户端错误处理和调试 |
快速开始
基础异常抛出
import asyncio
from simplejrpc.app import ServerApplication
from simplejrpc.exceptions import RPCException, ValidationError, UnauthorizedError
app = ServerApplication("app.socket")
@app.route(name="hello")
async def hello(name: str = None):
"""问候接口示例"""
if not name:
raise ValidationError("姓名参数不能为空")
if name == "admin":
raise UnauthorizedError("管理员账户禁止访问")
return {"message": f"Hello, {name}!"}
if __name__ == "__main__":
asyncio.run(app.run())
响应示例
当抛出异常时,框架会自动格式化为统一的错误响应:
{
"jsonrpc": "2.0",
"result": {
"code": 400,
"meta": {"endpoint": null, "close": 1},
"data": null,
"msg": "姓名参数不能为空"
},
"id": 1
}
内置异常类型
框架提供了丰富的内置异常类,覆盖常见的业务场景。所有异常类均继承自 RPCException
。
重要说明
所有异常类均继承自 RPCException
,确保统一的异常处理机制。
异常类型详览
异常类 | 描述 | 使用场景 | 示例 |
---|---|---|---|
RPCException | 基础异常类 | 通用业务异常 | raise RPCException("操作失败") |
UnauthorizedError | 访问未授权资源 | 身份验证失败、权限不足 | raise UnauthorizedError("用户未登录") |
ValidationError | 参数验证失败 | 请求参数格式错误、必填参数缺失 | raise ValidationError("邮箱格式不正确") |
FileNotFoundError | 文件未找到 | 请求的资源不存在 | raise FileNotFoundError("用户不存在") |
ValueError | 参数值错误 | 参数值超出范围、类型不匹配 | raise ValueError("年龄必须在0-150之间") |
RuntimeError | 程序运行错误 | 系统内部错误、第三方服务异常 | raise RuntimeError("数据库连接失败") |
AttributeError | 对象属性错误 | 访问不存在的对象属性 | raise AttributeError("对象缺少必要属性") |
相关信息
框架提供的异常 code 状态码都是 400
国际化支持
异常消息支持国际化,可以根据客户端语言返回对应的错误信息。
补充说明:
异常处理建议
- 选择合适的异常类型:根据错误性质选择最合适的异常类
- 提供详细错误信息:包含足够的上下文信息,便于调试和用户理解
- 统一错误码管理:为不同类型的错误定义统一的错误码
- 支持国际化:为全球化应用提供多语言错误信息
- 编写异常测试:确保异常处理逻辑的正确性
自定义错误码和数据
在实际使用中,RPCException
支持自定义错误码和附加数据,提供更灵活的异常处理:
# 自定义错误码和消息
raise RPCException(code=410, msg="用户不存在")
# 包含附加数据的异常
raise RPCException(
code=410,
msg="用户不存在",
data={"user_id": 123, "suggestion": "请检查用户ID是否正确"}
)
# 业务场景示例
@app.route(name="get_user_profile")
async def get_user_profile(user_id: int):
user = await find_user(user_id)
if not user:
raise RPCException(
code=404,
msg="用户资料不存在",
data={
"user_id": user_id,
"timestamp": datetime.now().isoformat(),
"suggestion": "请确认用户ID是否正确"
}
)
return {"profile": user.to_dict()}
响应示例:
{
"jsonrpc": "2.0",
"result": {
"code": 404,
"meta": {"endpoint": "get_user_profile", "close": 1},
"data": {
"user_id": 123,
"timestamp": "2024-01-15T10:30:00",
"suggestion": "请确认用户ID是否正确"
},
"msg": "用户资料不存在"
},
"id": 1
}