• Flask框架——应用错误处理


    目录

    错误日志工具

    错误处理器

    注册错误处理器

    自定义错误页面

    自定义错误处理器HTTP代码

    通用错误处理器


    上篇文章我们学习Flask框架——基于类的视图,这篇文章学习Flask框架——应用错误处理。

    即使我们的代码是百分百正确,但是还是会时常看见出错,这是因为和代码相关联的东西会出错,例如:

    • 客户端中断了请求,但应用程序还在读取数据;

    • 数据库已经过载,无法处理查询;

    • 文件系统没有存储空间;

    • 硬盘崩溃,后台服务过载;

    • 使用的库出现程序错误;

    • 服务器与另一个系统的网络连接出错;

    除了这些错误还有很多错误,在生产环境下,我们通过把出错情况记录到日志里面。但这不是最好的处理错误方式。接下来我们学习更好的出错处理方式。

    错误日志工具

    当web应用程序运行发生错误时,我们可以通过日志文件来找错误信息并处理错误,但只要有足够多的用户触发了该错误或不同的错误,即使是很简单的错误,这样通过日志文件来找错误信息并处理错误就会变得很困难。

    这时我们可以使用Sentry来处理应用错误,Sentry可以统计重复错误、捕获堆栈数据和本地变量用于排错,并在发生新的错误时或按指定频度发送电子邮件。

    在使用Sentry时,执行如下代码安装flask依赖的sentry-sdk客户端:

    pip install sentry-sdk[flask]
    

    安装成功后,我们需要dsn值,dsn可以通过以下方式获取:

    1、进入sentry注册登录网站注册账号,如下图所示:

    这些注册信息可以随意填写,但Email和password需要我们记住,用来登录查看sentry发送的错误信息。

    2、创建项目,如下图所示:

    这里我们选择了flask,点击创建项目就会跳转到如下网页:

    我们通过官网提供的示例代码来演示如何使用sentry,代码如下所示:

    1. from flask import Flask
    2. import sentry_sdk
    3. from sentry_sdk.integrations.flask import FlaskIntegration
    4. sentry_sdk.init(       #初始化配置
    5.     dsn="YOUR_DSN_HERE",      #设置dsn值
    6.     integrations=[FlaskIntegration()],    #整合器
    7.     traces_sample_rate=1.0      #捕获的性能数据量,值在0-1之间
    8. )
    9. app = Flask(__name__)
    10. if __name__ == '__main__':
    11.     app.run()

    首先导入sentry的库和方法,在进行sentry_sdk的初始化配置,接着编写一个视图函数,代码如下所示:

    1. @app.route('/debug-sentry')
    2. def trigger_error():
    3.     division_by_zero = 1 / 0

    视图函数的语法没有问题,但由于0不能为被除数,所以当我们访问/debug-sentry的URL时,会触发一个错误,这个错误信息会被sentry捕获。

    运行flask程序,并访问http://127.0.0.1:5000/debug-sentry,如下图所示:

    该错误信息大概是说:服务器遇到内部错误,服务器过载或应用程序出错。

    登录sentry后,如下图所示:

    这样我们就成功捕获了错误信息和出错的次数了。

    错误处理器

    在Flask中发生错误时,会返回一个相应的HTTP状态码,状态码400~499表示客户端的请求数据或与之相关的错误,状态码500~599表示服务器或应用本身的错误。

    例如:在我们请求一个不存在的URL链接时,会发出一个404 Not Found错误,如下图所示:

    当发生错误时,向用户显示我们自定义的出错页面时,我们可以使用错误处理器。

    错误处理器是一个函数,类似视图函数的函数,当发生某类错误时,返回一个传递了正在处理的错误的实例响应。

    注册错误处理器

    在使用错误处理器时,需要先注册错误处理器,注册错误处理器有两种方法:使用errorhandler装饰函数注册、使用register_error_handler()来注册 ,示例代码如下:

    1. #使用装饰器函数注册
    2. @app.errorhandler(werkzeug.exceptions.BadRequest)  #传递子类BadRequest
    3. #@app.errorhandler(400)       #或传递标准HTTP代码
    4. def handle_bad_request(e):
    5.     return '错误请求'400     #返回出错代码400
    6.     
    7. #使用register_error_handler()注册
    8. def handle_bad_request(e):
    9.     return 'bad request!'400    #返回出错代码400
    10. app.register_error_handler(400, handle_bad_request)

    在使用errorhandler装饰器函数注册时,需要传入werkzeug.exceptions.HTTPException的子类,例如BadRequest或者传递标准HTTP代码,如400,在返回响应时需要设置出错代码。

    自定义错误页面

    为了更能告诉用户错误信息,我们可以自定义错误页面,首先注册一个错误处理器器,再abort()函数,该函数可以中止请求,产生HTTP错误。Flask程序示例代码如下:

    1. import werkzeug
    2. from flask import Flask, abort
    3. app=Flask(__name__)
    4. @app.errorhandler(400)
    5. def handle_bad_request(e):
    6.     return '错误请求'400   #返回错误信息
    7. @app.route('/')
    8. def hello_world():
    9.     abort(400)      #使用abort()函数,传递400HTTP代码
    10. if __name__ == '__main__':
    11.     app.run()

    启动Flask程序,访问http://127.0.0.1:5000/时,网页会显示错误请求。

    除了上面返回错误信息的数据格式,我们可以将错误信息以JSON的格式来返回,示例代码如下:

    1. from flask import Flask, abort,jsonify
    2. app=Flask(__name__)
    3. @app.errorhandler(404)       #注册404错误处理器
    4. def resource_not_found(e):
    5.     return jsonify(error=str(e)), 404    #使用jsonify()方法接收错误对象e,并传入错误HTML代码404
    6. @app.route('/')
    7. def hello_world():
    8.     abort(404,description="Resource not found")          #抛出错误处理器错误信息
    9. if __name__ == '__main__':
    10.     app.run(debug=True)

    启动Flask程序,访问http://127.0.0.1:5000/时,网页会显示如下内容:

    1. {
    2.   "error": "404 Not Found: Resource not found"
    3. }

    自定义错误处理器HTTP代码

    注意:Werkzeug 无法识别非标准HTTP代码,当返回出错代码不是标准的HTTP代码时,会报错,例如:返回出错代码1000

    KeyError: "'1000' is not a recognized HTTP error code. Use a subclass of HTTPException with that code instead."
    

    Werkzeug 无法识别非标准HTTP代码,也就是使用上面的方法无法注册非标准HTTP代码的错误处理器。

    这时我们自定义一个HTTPException子类, 注册并抛出异常类,Flask程序示例代码如下:

    1. import werkzeug
    2. from flask import Flask, abort, render_template
    3. app=Flask(__name__)
    4. class InsufficientStorage(werkzeug.exceptions.HTTPException):  #自定义HTTP错误子类
    5.     code=1000
    6.     description = 'Not enough storage space.'
    7. def handle_1000(e):
    8.     return '服务器无法存储完成请求所必须的内容',1000     #返回错误信息及HTTP代码
    9. app.register_error_handler(InsufficientStorage, handle_1000)    #注册错误处理器
    10. @app.route('/')
    11. def hello_world():
    12.     raise InsufficientStorage()    #抛出错误处理器错误信息
    13. if __name__ == '__main__':
    14.     app.run(debug=True)

    这里我们创建了名为InsufficientStorage的子类,子类里面的内容可以是随意的,再创建一个名为handle_1000()的函数,该函数返回错误请求和HTTP代码。最后使用register_error_handler()方法注册错误处理器——InsufficientStorage子类和handle_507。

    启动Flask程序,访问http://127.0.0.1:5000/,如下图所示:

    通用错误处理器

    通用错误处理器就是把HTTP出错信息转换为JSON并展示在网页中,示例代码如下所示:

    1. import werkzeug
    2. from flask import Flask, abort, render_template
    3. from flask import json
    4. from werkzeug.exceptions import HTTPException
    5. app=Flask(__name__)
    6. @app.errorhandler(HTTPException)    #注册错误处理器
    7. def handle_exception(e):        #错误处理器函数传入错误对象e
    8.     response = e.get_response()     #获取错误响应
    9.     response.data = json.dumps({    #编辑错误响应内容
    10.         "code": e.code,
    11.         "name": e.name,
    12.         "description": e.description,
    13.     })
    14.     response.content_type = "application/json"  #设置响应类型
    15.     return response
    16. @app.route('/')
    17. def hello_world():
    18.     abort(501)             #使用abort()传入501错误代码
    19. if __name__ == '__main__':
    20.     app.run(debug=True)

    首先使用errorhandler装饰器注册错误处理器,并定义错误处理器函数接收错误对象e,根据错误对象e来编辑返回错误响应内容。

    启动Flask程序,访问http://127.0.0.1:5000/,如下图所示:

    好了,Flask框架——应用错误处理就学到这里了,感谢观看,下篇文章我们学习Flask框架——Bootstrap-Flask使用

    公众号:白巧克力LIN

    该公众号发布Python、数据库、Linux、Flask、自动化测试、Git等相关文章!

    - END -

  • 相关阅读:
    三分钟带你JAVA入门,1000多个人看了都说好
    FANUC机器人零点复归的报警原因分析和零点标定相关步骤
    【acwing总结】快速排序
    iOS提词器,画中画
    uniapp 获取设备唯一标识(OAID、AAID、AndroidID、IMEI等)插件 Ba-IdCode
    mysql的left join原理【总结版本】
    动漫主题dreamweaver作业静态HTML网页设计——仿京东(海贼王)版本
    Keras:ModelCheckpoint和model.fit的verbose有什么差异?
    JavaScript基础
    合并两个有序数组(美团面试)
  • 原文地址:https://blog.csdn.net/weixin_52122271/article/details/126169158