如何使用@app.errorhandler同时捕获多个异常类与HTTP状态码
问题根因
叠加@app.errorhandler装饰器本身是Flask官方支持的合法写法,你遇到的报错本质是Mypy对Flask装饰器的类型推断限制:
- 当
errorhandler接收自定义异常类作为参数时,要求被装饰函数的入参为对应异常类实例 - 当
errorhandler接收HTTP状态码作为参数时,要求被装饰函数的入参为HTTPException实例/状态码数值
两种场景对函数签名的要求存在差异,叠加装饰器时Mypy会以最外层装饰器的校验规则为准,就会出现顺序改变、参数名修改后报错的问题。
推荐实现方式
方式1:显式调用add_error_handler注册(无类型报错)
不需要叠加装饰器,直接通过Flask实例的方法显式注册两个处理规则,完全规避类型推断问题,可读性也更高:
class BadRequestError(Exception): pass def serve_400_error(error: Exception) -> Response: return client_error_page(400) # 分别注册状态码和自定义异常 app.add_error_handler(400, serve_400_error) app.add_error_handler(BadRequestError, serve_400_error)
方式2:调整类型标注兼容装饰器写法
如果要保留装饰器叠加的写法,调整参数的类型标注,同时固定装饰器顺序:
from typing import Union from werkzeug.exceptions import HTTPException class BadRequestError(Exception): pass # 装饰器顺序:异常类注册放在最下层,状态码注册放在上层 @app.errorhandler(400) @app.errorhandler(BadRequestError) def serve_400_error(error: Union[BadRequestError, HTTPException]) -> Response: return client_error_page(400)
如果要将参数名改为_且不需要用到参数,可以在参数后加忽略注释解决报错:
@app.errorhandler(400) @app.errorhandler(BadRequestError) def serve_400_error(_: Union[BadRequestError, HTTPException]) -> Response: # type: ignore[unused-argument] return client_error_page(400)
内容的提问来源于stack exchange,提问作者Garrett
相关产品推荐
相关产品推荐

