Flask 全局异常处理

news/2024/11/29 4:43:04/

文章目录

  • 一、异常处理流程
    • 1.1 异常注册
      • 1.1.1 装饰器模式
      • 1.1.2 工厂模式
    • 1.2 异常触发
      • 1.2.1 assert触发异常
      • 1.2.2 raise触发异常
      • 1.2.3 abort触发异常
    • 1.3 异常处理
      • 1.3.1 正常请求
      • 1.3.2 异常请求
  • 二、自定义异常(客户端异常)
  • 三、服务端异常
  • 参考资料

异常分为客户端异常和服务端异常,flask 中的异常处理分为三步走:异常注册、异常触发、异常处理。

关于客户端/服务端异常,先看段样例代码:

from flask import *
from paddlenlp import Taskflow
from werkzeug.exceptions import HTTPExceptionapp = Flask(__name__)
app.config['JSON_AS_ASCII'] = False@app.errorhandler(Exception)
def handle_500_exception(e):# pass through HTTP errorsif isinstance(e, HTTPException):return e# now you're handling non-HTTP exceptions onlyreturn render_template("500_generic.html", e=e), 500@app.errorhandler(HTTPException)
def handle_exception(e):response = e.get_response()response.data = json.dumps({"code": e.code,"name": e.name,"description": e.description,})response.content_type = "application/json"return responseclass RequestParamException(HTTPException):code = 400def handle_param_exception(e):response = e.get_response()response.data = json.dumps({"code": e.code,"name": "子类:RequestParamException 处理的异常。","description": e.description,})response.content_type = "application/json"return response@app.route('/add_user', methods=['POST'])
def add_documents():data = request.get_json()user = data['user']if user is None or len(user) <= 0:raise RequestParamException(description="user 不能为 None 或 ''。")return {"user": user}, 201if __name__ == '__main__':app.register_error_handler(RequestParamException, handle_param_exception)app.run(debug=True)

一、异常处理流程

1.1 异常注册

常用的异常注册的模式包括两种:

  • 装饰器模式:@app.errorhandler
  • 工厂模式: app.register_error_handler()

1.1.1 装饰器模式

使用装饰器模式注册异常时,针对Exception异常(服务端异常)和HttpException异常(客户端异常),注册的时候可以指定具体处理的异常类型,也可以统一处理。

服务端异常注册:

@app.errorhandler(Exception)
def handle_error(e):"""Handle errors, formatting them as JSON if requested"""......

客户端异常注册:

@app.errorhandler(HTTPException)
def handle_error(e):"""Handle errors, formatting them as JSON if requested"""......

1.1.2 工厂模式

服务端异常注册:

app.register_error_handler(Exception, handle_error)

客户端异常注册:

app.register_error_handler(HTTPException, handle_error)

1.2 异常触发

异常触发的方式通常有以下几种:

1.2.1 assert触发异常

assert语句又称作断言,指的是程序期望满足指定的条件。定义的约束条件不满足的时候,它会触发AssertionError异常,所以assert语句可以当作条件式的raise语句。

assert 逻辑表达式, data      

data是可选的,通常是一个字符串,当表达式的结果为False时,作为异常类型的描述信息使用。
assert语句等同于:

if not 逻辑表达式:raise AssertionError(data)

1.2.2 raise触发异常

raise [exceptionName [(reason)]] 

其中,用 [] 括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述。如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果之前没有触发异常,触发RuntimeError;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息。

  • raise
  • raise exceptionName
  • raise exceptionName(reason)

1.2.3 abort触发异常

在视图函数执行过程中,我们可以使用abort函数立即终止视图函数的执行。通过abort函数,可以返回一个app.aborter中存在的错误状态码,表示出现的错误信息。类似于python中raise。

abort(404)

1.3 异常处理

在上述客户端全局异常捕获过程中,异常的处理方法为 handle_exception(e)
客户端的所有请求都囊括了,404、405、400 等等,一旦这些异常触发,都会执行到 handle_exception(e) 方法中,最后将异常信息返回给客户端。handle_exception(e) 方法里面的具体内容如下:

@app.errorhandler(HTTPException)
def handle_exception(e):response = e.get_response()response.data = json.dumps({"code": e.code,"name": e.name,"description": e.description,})response.content_type = "application/json"return response

1.3.1 正常请求

请求内容:

curl --request POST \--url http://127.0.0.1:5000/add_user \--header 'Content-Type: application/json' \--data '{"user":"diego"}'

返回结果:

{"user": "diego"
}

1.3.2 异常请求

(1)触发 404 异常

请求内容:

curl --request POST \--url http://127.0.0.1:5000/add_user2 \--header 'Content-Type: application/json' \--data '{"user":"diego"}' | jq

返回结果:

{"code": 404,"description": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.","name": "Not Found"
}

(2) 触发 405 异常

请求内容:

curl --request GET \--url http://127.0.0.1:5000/add_user \--header 'Content-Type: application/json' \--data '{"user":"diego"}' | jq

返回结果:

{"code": 405,"description": "The method is not allowed for the requested URL.","name": "Method Not Allowed"
}

二、自定义异常(客户端异常)

我们可以在 HTTPException 基础上自定义异常信息,比如在参数不符合要求,抛出异常。当子类异常与父类异常同时存在时,优先让子类异常捕获。

注意:不要直接触发HttpException异常,这样会导致错误不能被正常捕获并处理。
在Flask的异常处理流程中,首先会单独判断一下是否HTTPException异常,如果是的话转入handle_http_exeption处理器进行处理。然后handle_http_exeption处理逻辑中,会默认访问code属性。但是直接触发HTTPException时是无法设置code属性的。因此这时会引发新的异常,导致错误处理不会走我们注册的处理程序,造成莫名其妙的错误。
这里,建议我们要么触发类似NotFound这些基于HTTPException扩展的异常,要么可以基于HTTPException继承自定义的异常。

(1)定义异常

## 定义异常类
class RequestParamException(HTTPException):code = 400
## 定义异常处理方法
def handle_param_exception(e):response = e.get_response()response.data = json.dumps({"code": e.code,"name": "子类:RequestParamException 处理的异常。","description": e.description,})response.content_type = "application/json"return response  

(2)注册异常

这里,在app.py文件的main函数中,使用工厂模式注册RequestParamException异常:

if __name__ == '__main__':app.register_error_handler(RequestParamException, handle_param_exception)app.run()

(3)异常触发
请求内容:

curl --request POST \--url http://127.0.0.1:5000/add_user \--header 'Content-Type: application/json' \--data '{"user":""}' | jq

返回结果:

{"code": 400,"description": "user 不能为 None 或 ''。","name": "子类:RequestParamException 处理的异常。"
}

三、服务端异常

@app.errorhandler(Exception)
def handle_500_exception(e):# pass through HTTP errorsif isinstance(e, HTTPException):return e# now you're handling non-HTTP exceptions onlyreturn render_template("500_generic.html", e=e), 500

服务端异常 HTTPException 是捕获不了的,只能单独处理。

参考资料

  • flask 全局异常处理:https://blog.csdn.net/yy_diego/article/details/127775426
  • Python Web异常处理:https://blog.csdn.net/aizaiyishunjian/article/details/129892499

http://www.ppmy.cn/news/487114.html

相关文章

scanpy单细胞分析流程

梳理一下scanpy单细胞分析流程&#xff08;处理的是scRNA-seq&#xff09;。 先上一张流程图&#xff1a; scanpy单细胞分析流程 import scanpy as scRead data 常用的文件格式有两种&#xff0c;分别是h5ad和10X mtx # read h5ad adata sc.read()# read 10X mtx adata …

python:使用Scikit-image库的slic函数分割遥感图像

作者:CSDN @ _养乐多_ 本文记录了使用Scikit-image库的skimage.segmentation模块中的slic函数,进行超像素分割的代码。 文章目录 一、slic函数详解二、代码一、slic函数详解 在Scikit-image库的skimage.segmentation模块中,slic函数用于进行超像素分割。该函数的参数含义如…

元宇宙虚拟人解决方案:创新变革营销模式,用科技助力营销

近两年&#xff0c;元宇宙虚拟人大火&#xff0c;虚拟人与品牌联合已经成为了一种新的营销趋势&#xff0c;如阿喜与兰蔻、柳夜熙与娇韵诗、A-Soul与Keep……这些品牌商业合作实现了虚拟人商业的变现。虚拟人可以与各虚实场景交互&#xff0c;拉近与用户的距离&#xff0c;增强…

HAYDON黑洞全球高端美妆专卖店设计分享!

作为国内首个提出不可定义的黑洞之旅概念的高端美妆体验店&#xff0c;通过邀请顶尖的专卖店设计公司&#xff0c;HAYDON黑洞把首家线下体验店落户在了武汉楚河汉街。 随着首店开启&#xff0c;众美妆、时尚、生活方式领域的达人纷纷到场打卡&#xff0c;这个沉浸式的黑洞之旅体…

什么是黑洞路由?

黑洞路由 定义&#xff1a; 一条路由无论是静态还是动态&#xff0c;都需要关联到一个出接口&#xff0c;在众多的出接口中&#xff0c;有一种接口非常特殊&#xff0c;即Null&#xff08;无效&#xff09;接口&#xff0c;这种类型的接口只有一个编号0&#xff0c;类似&…

数字时代,元宇宙场景下的营销策略有哪些?

由于数字时代的到来&#xff0c;消费者行为已经发生了变化。越来越多的人使用互联网来学习、工作、娱乐和购物。元宇宙承诺并推广一种“物质数字化&#xff08;物理环境或有形物体与数字化或在线技术驱动体验的结合&#xff09;”的解决方案。它的目标是通过模糊现实生活和虚拟…

元境技术助力元宇宙营销 联合发起商广协元宇宙营销研究院

2022年11月28日&#xff0c;以“跨越周期”为主题的第十届中国数字营销峰会正式举行。中国商务广告协会元宇宙营销应用研究院&#xff08;以下简称&#xff1a;元宇宙研究院&#xff09;正式揭牌成立&#xff0c;由阿里巴巴元境、百度、蓝色光标等20多家企业联合发起。元境作为…

金融黑洞理论

信息的度量 单一离散信息的自信息量&#xff0c;一个信息出现的概率为p&#xff0c;则这一信息包含的信息量i&#xff0c;i-lga p 信息熵&#xff0c;实际上离散信源发出的不是单一信息&#xff0c;而是多个信息&#xff08;或符号的集合&#xff09;。例如&#xff0c;经过数…