十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Litestar 异常体系完全指南:从异常层次、响应构建到自定义处理器

Litestar 异常体系完全指南:从异常层次、响应构建到自定义处理器 Litestar 异常体系完全指南从异常层次、响应构建到自定义处理器【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar导读本文以 docs/reference/exceptions.rst 的 API 参考为骨架深入剖析 Litestar轻量、灵活、可扩展的 ASGI 框架完整的异常体系包括统一异常基类LitestarException、面向 HTTP/WebSocket 的语义化异常、异常到 HTTP 响应的自动转换机制create_exception_response/create_debug_response、以及通过exception_handlers自定义错误处理的方式。读完本文你将能准确选择合适的异常类型抛出、理解异常响应生成的全过程并写出生产级可用的自定义异常处理器。一、异常模块概览与整体架构Litestar 的异常体系集中在litestar/exceptions/目录下按职责划分为四个子模块模块文件职责关键导出litestar/exceptions/base_exceptions.py所有异常的公共基类与通用异常LitestarException、MissingDependencyException、SerializationException、LitestarWarning、LitestarDeprecationWarninglitestar/exceptions/http_exceptions.pyHTTP 语义化异常携带状态码、响应头与附加数据HTTPException、ClientException、ValidationException、NotFoundException等litestar/exceptions/websocket_exceptions.pyWebSocket 连接异常与断开事件WebSocketException、WebSocketDisconnectlitestar/exceptions/dto_exceptions.pyDTO数据传输对象工厂相关异常DTOFactoryException、InvalidAnnotationException所有公共类型统一从 litestar/exceptions/init.py 再导出因此业务代码只需from litestar.exceptions import ...即可使用全部异常类型而无需关心内部文件布局。从继承关系看依据 base_exceptions.py 与 http_exceptions.py整棵异常树的顶层是Exception └── LitestarException # 所有 Litestar 异常的公共基类 ├── MissingDependencyException ├── SerializationException ├── HTTPException # 所有 HTTP 错误响应的基类 │ ├── ImproperlyConfiguredException │ ├── ClientException # 4xx 客户端错误 │ │ ├── ValidationException │ │ ├── NotAuthorizedException │ │ ├── PermissionDeniedException │ │ ├── NotFoundException │ │ ├── MethodNotAllowedException │ │ ├── RequestEntityTooLarge │ │ └── TooManyRequestsException │ └── InternalServerException # 5xx 服务端错误 │ ├── ServiceUnavailableException │ ├── NoRouteMatchFoundException │ └── TemplateNotFoundException ├── DTOFactoryException │ └── InvalidAnnotationException ├── WebSocketException │ └── WebSocketDisconnect └── (其余直接继承的异常)二、基础异常LitestarException 与通用异常2.1 统一基类 LitestarExceptionLitestarException源码见 base_exceptions.py是所有 Litestar 异常的根。它定义了类属性detail: str并通过构造函数统一了异常的实例化约定位置参数*args会被逐个转为字符串若未通过detail关键字提供详情则将第一个位置参数作为detail若类上预定义了detail类属性则作为默认详情兜底最终self.detail保存详情其余参数交给标准库Exception。其__repr__返回类名 - detail形式便于日志与调试输出__str__则拼接所有位置参数与detail。2.2 MissingDependencyException可选依赖缺失MissingDependencyException同时继承LitestarException与ImportError仅在模块依赖的可选包未安装时抛出。其构造函数签名base_exceptions.py为MissingDependencyException(package: str, install_package: str | None None, extra: str | None None)它自动生成一条包含安装指令的错误消息例如提示运行pip install litestar[extra]或单独安装对应包帮助使用者快速修复依赖问题。2.3 SerializationException 与警告类型SerializationException对象编码或解码序列化/反序列化失败时抛出LitestarWarning(UserWarning)所有 Litestar 警告的公共基类LitestarDeprecationWarning(DeprecationWarning)标记即将废弃 API 的警告类型。三、HTTP 异常面向响应构造的语义化异常3.1 HTTPException 基类HTTPExceptionhttp_exceptions.py是构造 HTTP 错误响应的基础。它以类属性形式声明了四个核心字段类属性类型含义默认值status_codeintHTTP 状态码500HTTP_500_INTERNAL_SERVER_ERRORdetailstr异常详情/错误消息由构造参数决定headersdict[str, str] \| None附加到响应的响应头Noneextradict[str, Any] \| list[Any] \| None附加到异常上的额外数据会出现在响应体中None构造函数签名HTTPException( *args, detail: str , status_code: int | None None, headers: dict[str, str] | None | EmptyType Empty, extra: dict[str, Any] | list[Any] | None | EmptyType Empty, )几个关键行为可在 tests/unit/test_exceptions.py 的测试中得到印证status_code为None时回落到类属性默认值headers/extra使用哨兵值Empty区分「未传」沿用类属性与「显式传 None」清除类属性两种场景未提供detail时自动使用HTTPStatus(status_code).phrase即标准状态码短语作为详情构造完成后args被重写为(f{status_code}: {detail}, *args)因此str(exc)输出形如400: Bad Request的信息。3.2 预置的 HTTP 异常族Litestar 按语义预置了常用的 HTTP 异常覆盖 4xx 与 5xx 场景全部定义于 http_exceptions.py异常类继承默认状态码语义ImproperlyConfiguredExceptionHTTPException, ValueError500应用配置不当启动期问题ClientExceptionHTTPException400通用客户端错误基类ValidationExceptionClientException, ValueError400客户端数据校验失败同时是ValueError便于except ValueError捕获NotAuthorizedExceptionClientException401缺少有效认证凭据PermissionDeniedExceptionClientException403请求已被理解但无权限执行NotFoundExceptionClientException, ValueError404找不到请求的资源MethodNotAllowedExceptionClientException405目标资源不支持该请求方法RequestEntityTooLargeClientException413请求实体过大预置detailTooManyRequestsExceptionClientException429请求频率超限限流场景InternalServerExceptionHTTPException500服务器内部错误基类ServiceUnavailableExceptionInternalServerException503服务暂不可用如维护中NoRouteMatchFoundExceptionInternalServerException500未找到匹配路由TemplateNotFoundExceptionInternalServerException500引用的模板文件不存在构造时需传template_name值得注意的是ValidationException与NotFoundException同时混入ValueError这意味着业务代码中既可按 Litestar 语义捕获也可按标准库ValueError语义捕获ImproperlyConfiguredException同理混入了ValueError。3.3 自定义 HTTP 异常基于类属性与构造参数的组合可以非常轻量地定义自定义异常例如from litestar.exceptions import HTTPException from litestar.status_codes import HTTP_400_BAD_REQUEST class CustomHTTPExceptionWithExtra(HTTPException): status_code HTTP_400_BAD_REQUEST extra {key: value}对应测试见 tests/unit/test_exceptions.py。类属性extra/headers会作为响应附加数据的默认值。四、WebSocket 异常与 DTO 异常4.1 WebSocketException 与 WebSocketDisconnectWebSocket 场景有独立的异常类型websocket_exceptions.pyWebSocketException(LitestarException)WebSocket 相关事件的通用异常携带code: int关闭码。文档注释约定自定义异常应使用4000 区间的关闭码其余标准关闭码以WS_前缀定义在litestar.status_codes中。构造函数默认为code4500。WebSocketDisconnect(WebSocketException)表示 WebSocket 断开事件默认关闭码为WS_1000_NORMAL_CLOSURE即 1000。4.2 DTO 异常DTO 工厂相关异常定义在 litestar/exceptions/dto_exceptions.pyDTOFactoryException(LitestarException)DTO 工厂异常的基类InvalidAnnotationException(DTOFactoryException)DTO 工厂收到非预期类型参数注解无效时抛出典型场景是给 DTO 类型传入了不受支持的泛型参数。五、异常如何变成 HTTP 响应这是 Litestar 异常体系最核心的机制。请求处理过程中抛出的异常最终会通过litestar/exceptions/responses/__init__.py中的工具函数转换为标准的Response对象。5.1 ExceptionResponseContent异常响应内容模型ExceptionResponseContent是一个dataclasslitestar/exceptions/responses/init.py字段与HTTPException一一对应字段类型说明status_codeint异常状态码detailstr异常详情media_typeMediaType \| str响应媒体类型headersdict[str, str] \| None响应头extradict \| list \| None附加数据其to_response(requestNone)方法负责真正构造Response将非空字段组装为响应体内容若media_type不是 JSON 则先经过 JSON 编码复用litestar.serialization.encode_json并透传请求级type_encoders。5.2 create_exception_response统一的异常转响应入口create_exception_response(request, exc)litestar/exceptions/responses/init.py是框架内部将任意异常转为响应的核心函数处理逻辑如下状态码判定若exc是HTTPException或具有status_code属性的异常如 Starlette 的HTTPException则取该状态码否则一律回落到HTTP_500_INTERNAL_SERVER_ERROR500详情判定只有LitestarException且状态码非 500 时才把exc.detail写入响应非 Litestar 异常或 500 异常统一返回Internal Server Error避免把内部实现细节泄露给客户端对应测试见 tests/unit/test_exceptions.py媒体类型优先取request.route_handler.media_type即当前路由处理器的媒体类型若路由未解析如 404 场景则回落到MediaType.JSON响应构造将以上信息组装为ExceptionResponseContent并调用to_response(requestrequest)。tests/unit/test_exceptions.py中分别用 Litestar HTTP 异常、Starlette HTTP 异常、普通异常三类输入验证了该工具函数的行为test_exceptions.py可作为行为契约参考。5.3 create_debug_response开发期调试响应create_debug_response(request, exc)转发到 litestar/exceptions/responses/_debug_response.py 中的同名实现根据请求头Accept决定输出形态Accept: text/html→ 返回带交互式 traceback 的HTML 页面帧折叠、源码行高亮、__cause__链展示样式与脚本模板位于 litestar/exceptions/responses/templates/Accept: application/json→ 返回{details: 纯文本 traceback, status_code: 500}的 JSON其他情况 → 返回纯文本 traceback。该响应固定使用HTTP_500_INTERNAL_SERVER_ERROR状态码其 HTML 渲染能力依赖inspect.getinnerframes与traceback.format_exception并支持line_limit控制每帧显示的代码上下文行数默认 15 行。六、自定义异常处理器exception_handlers框架默认把异常交给上述转换逻辑处理但你可以通过应用配置exception_handlers完全接管某类异常的处理实现自定义错误响应格式如统一 JSON 结构、日志埋点、指标上报等。6.1 配置入口Litestar应用通过exception_handlers关键字接收「异常类型 → 处理函数」的映射该字段定义于 litestar/config/app.py 的AppConfig中默认空字典。6.2 完整示例仓库示例 docs/examples/exceptions/override_default_handler.py 演示了覆盖默认处理器from litestar import Litestar, MediaType, Request, Response, get from litestar.exceptions import HTTPException from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR def plain_text_exception_handler(_: Request, exc: Exception) - Response: Default handler for exceptions subclassed from HTTPException. status_code getattr(exc, status_code, HTTP_500_INTERNAL_SERVER_ERROR) detail getattr(exc, detail, ) return Response( media_typeMediaType.TEXT, contentdetail, status_codestatus_code, ) get(/) async def index() - None: raise HTTPException(detailan error occurred, status_code400) app Litestar( route_handlers[index], exception_handlers{HTTPException: plain_text_exception_handler}, )要点处理器签名固定为(request: Request, exc: Exception) - Response通过getattr(exc, status_code, ...)与getattr(exc, detail, )兼容任意异常不限于HTTPException映射键可以是异常基类如HTTPException此时其所有子类都会走该处理器也可以是具体异常类型实现更细粒度的分流。6.3 分层处理与默认处理器异常处理器遵循分层解析规则路由处理器层、控制器层、应用层均可配置exception_handlers内层未命中时逐级向外层回退示例 docs/examples/exceptions/layered_handlers.py 展示了这种分层注册方式。若不配置任何处理器则回落到第 5 节描述的默认异常转响应逻辑框架内置的 500 调试页面与 404 默认响应同样由该机制驱动。七、状态码常量status_codesHTTPException与 WebSocket 异常默认状态码全部取自 litestar/status_codes.py 中定义的Final常量推荐业务代码统一引用而非硬编码数字HTTP 状态码HTTP_100_CONTINUE100至HTTP_511_NETWORK_AUTHENTICATION_REQUIRED511全覆盖常用如HTTP_400_BAD_REQUEST、HTTP_401_UNAUTHORIZED、HTTP_403_FORBIDDEN、HTTP_404_NOT_FOUND、HTTP_405_METHOD_NOT_ALLOWED、HTTP_413_REQUEST_ENTITY_TOO_LARGE、HTTP_429_TOO_MANY_REQUESTS、HTTP_500_INTERNAL_SERVER_ERROR、HTTP_503_SERVICE_UNAVAILABLEWebSocket 关闭码WS_1000_NORMAL_CLOSURE1000至WS_1015_TLS_HANDSHAKE1015其中 1005、1006 属于不可由应用主动发送的保留码。八、最佳实践小结优先使用语义化异常4xx 场景抛出NotFoundException、NotAuthorizedException、ValidationException、TooManyRequestsException等比手写HTTPException(detail..., status_code404)更自文档化利用 detail/extra/headers 传递结构化信息extra会进入响应体可携带错误码、字段级校验错误等headers可携带Retry-After限流等响应头警惕 500 详情隐藏非LitestarException或 500 状态码的异常响应 detail 固定为Internal Server Error这是刻意的安全设计——不要把内部 traceback 暴露给客户端开发期调试保持默认的调试响应以便在浏览器中获得可折叠、带源码高亮的 HTML traceback生产环境务必覆盖 500 处理器避免信息泄露自定义处理器保持签名一致(request: Request, exc: Exception) - Response并善用getattr兜底读取status_code/detailWebSocket 自定义关闭码用 4000 区间标准码引用status_codes.WS_*常量。九、延伸阅读源码异常基类与 HTTP 异常见 litestar/exceptions/base_exceptions.py 与 litestar/exceptions/http_exceptions.py响应转换见 litestar/exceptions/responses/init.py 与 _debug_response.py示例docs/examples/exceptions/ 目录下包含覆盖默认处理器、分层处理器、按媒体类型输出等完整用例测试契约tests/unit/test_exceptions.py 覆盖了详情传递、状态码回落、extra/headers 默认值、Starlette 异常兼容、调试响应媒体类型等行为可作为异常语义的行为规范参考上层用法异常处理与生命周期钩子的配合可进一步阅读 docs/usage/exceptions.rst。【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表