Flask 全局异常处理

这篇具有很好参考价值的文章主要介绍了Flask 全局异常处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

from flask import *
from paddlenlp import Taskflow
from werkzeug.exceptions import HTTPException

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

@app.errorhandler(Exception)
def handle_500_exception(e):
    # pass through HTTP errors
    if isinstance(e, HTTPException):
        return e

    # now you're handling non-HTTP exceptions only
    return 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 response

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

@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}, 201


if __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 errors
    if isinstance(e, HTTPException):
        return e
    # now you're handling non-HTTP exceptions only
    return render_template("500_generic.html", e=e), 500

服务端异常 HTTPException 是捕获不了的,只能单独处理。文章来源地址https://www.toymoban.com/news/detail-495978.html

参考资料

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

到了这里,关于Flask 全局异常处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 1.6 服务器处理客户端请求

    客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。 从图中我们可以看出,服务器程序处理来自客户端的查询请求大致需要经过三个部分,分别是 连接管理 、 解析与优化 、 存储引擎 。 客户端进程可以采用我

    2024年02月11日
    浏览(37)
  • 【Zookeeper源码走读】第三章 服务器处理客户端请求的流程

    前一篇文章,已经大致介绍了Server的启动流程,在NIOServerCnxnFactory.start()方法中,启动了多个线程,其中就有接收socket报文的线程,代码如下: 注意这里,acceptThread是接收socket的线程(AcceptThread),acceptThread的初始化是在NIOServerCnxnFactory.configure()中实现的: NIOServerCnxnFactory.confi

    2024年02月02日
    浏览(47)
  • kakfa 3.5 kafka服务端处理消费者客户端拉取数据请求源码

    kafka服务端接收生产者数据的API在KafkaApis.scala类中,handleFetchRequest方法 replicaManager.fetchMessages 最后通过这个方法获得日志 通过readFromLocalLog查询数据日志 val readResult = read(tp, fetchInfo, limitBytes, minOneMessage) 遍历主题分区分别执行read内部函数执行查询操作 方法内部通过 partition.fe

    2024年02月10日
    浏览(42)
  • 【异常】客户端发起HTTPS请求报错,服务端返回400 Bad Request ,并且提示No required SSL certificate was sent

    HTTP响应码400表示客户端发送了一个无效的请求。这可能是由于请求中缺少必需的参数或格式不正确等原因导致的。服务器无法处理此请求并返回400响应码。如果您正在编写Web应用程序,建议在处理请求时检查请求的有效性,并在必要时返回400响应码以指示客户端请求无效。

    2024年02月11日
    浏览(49)
  • golang kafka客户端 sarama 在 rebalance时异常如何解决

    在使用sarama作为Kafka客户端的过程中,在进行消费者分区的rebalance操作时,可能会发生异常,在解决这些异常一般可以采取以下措施: 1. 异常处理:在consumer rebalance过程中如果发生异常,Sarama库将会发出错误事件(error event)。因此在编写代码时应该注册错误事件处理函数

    2024年02月10日
    浏览(48)
  • 由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求。

    问题描述:         由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求。 在实现向数据库中添加记录时,请求发送无效,参数也未传递到控制类。 原因分析: 可能存在两种出错原因: (1)语义

    2024年02月03日
    浏览(61)
  • Flask 全局异常处理

    异常分为客户端异常和服务端异常,flask 中的异常处理分为三步走:异常注册、异常触发、异常处理。 关于客户端/服务端异常,先看段样例代码: 常用的异常注册的模式包括两种: 装饰器模式: @app.errorhandler 工厂模式: app.register_error_handler() 1.1.1 装饰器模式 使用装饰器模式

    2024年02月10日
    浏览(35)
  • 线上 udp 客户端请求服务端客户端句柄泄漏问题

    本题分别从如下三个方面来分享: 问题描述 自定义连接池的编写 common_pool 的使用 线上有一个业务,某个通服务通知 udp 客户端通过向 udp 服务端(某个硬件设备)发送 udp 包来进行用户上线操作 当同时有大量的请求打到 udp 服务端的时候,udp 服务端的回包可能会在网络环境

    2024年02月09日
    浏览(64)
  • Java 网络编程 —— 客户端协议处理框架

    Java 对客户程序的通信过程进行了抽象,提供了通用的协议处理框架,该框架封装了 Socket,主要包括以下类: URL 类:统一资源定位符,表示客户程序要访问的远程资源 URLConnection 类:表示客户程序与远程服务器的连接,客户程序可以从 URLConnection 获得数据输入流和输出流

    2024年02月07日
    浏览(43)
  • Golang TCP/IP服务器/客户端应用程序,设计一个简单可靠帧传送通信协议。(并且正确处理基于流式控制协议,带来的应用层沾帧[沾包]问题)

    在 Golang 语言标准库之中提供了,对于TCP/IP链接、侦听器的高级封装支持,这易于上层开发人员轻松基于这些BCL(基础类库)实现期望的功能。 TCP/IP链接(客户端) net.Conn 接口 TCP/IP侦听器(服务器) net.Listener Golang 提供了易用的写入数据到远程(对端)实现,而不比像 C/C

    2024年01月24日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包