上篇文章我们学习Flask框架——基于类的视图,这篇文章学习Flask框架——应用错误处理。
即使我们的代码是百分百正确,但是还是会时常看见出错,这是因为和代码相关联的东西会出错,例如:
- 客户端中断了请求,但应用程序还在读取数据;
- 数据库已经过载,无法处理查询;
- 文件系统没有存储空间;
- 硬盘崩溃,后台服务过载;
- 使用的库出现程序错误;
- 服务器与另一个系统的网络连接出错;
除了这些错误还有很多错误,在生产环境下,我们通过把出错情况记录到日志里面。但这不是最好的处理错误方式。接下来我们学习更好的出错处理方式。
错误日志工具
当web应用程序运行发生错误时,我们可以通过日志文件来找错误信息并处理错误,但只要有足够多的用户触发了该错误或不同的错误,即使是很简单的错误,这样通过日志文件来找错误信息并处理错误就会变得很困难。
这时我们可以使用Sentry来处理应用错误,Sentry可以统计重复错误、捕获堆栈数据和本地变量用于排错,并在发生新的错误时或按指定频度发送电子邮件。
在使用Sentry时,执行如下代码安装flask依赖的sentry-sdk客户端:
pip install sentry-sdk[flask]
安装成功后,我们需要dsn值,dsn可以通过以下方式获取:
1、进入sentry注册登录网站注册账号,如下图所示:
这些注册信息可以随意填写,但Email和password需要我们记住,用来登录查看sentry发送的错误信息。
2、创建项目,如下图所示:
这里我们选择了flask,点击创建项目就会跳转到如下网页:
我们通过官网提供的示例代码来演示如何使用sentry,代码如下所示:
from flask import Flask
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init( #初始化配置
dsn="YOUR_DSN_HERE", #设置dsn值
integrations=[FlaskIntegration()], #整合器
traces_sample_rate=1.0 #捕获的性能数据量,值在0-1之间
)
app = Flask(__name__)
if __name__ == '__main__':
app.run()
首先导入sentry的库和方法,在进行sentry_sdk的初始化配置,接着编写一个视图函数,代码如下所示:
@app.route('/debug-sentry')
def trigger_error():
division_by_zero = 1 / 0
视图函数的语法没有问题,但由于0不能为被除数,所以当我们访问/debug-sentry的URL时,会触发一个错误,这个错误信息会被sentry捕获。
运行flask程序,并访问http://127.0.0.1:5000/debug-sentry,如下图所示:
该错误信息大概是说:服务器遇到内部错误,服务器过载或应用程序出错。
登录sentry后,如下图所示:
这样我们就成功捕获了错误信息和出错的次数了。
错误处理器
在Flask中发生错误时,会返回一个相应的HTTP状态码,状态码400499表示客户端的请求数据或与之相关的错误,状态码500599表示服务器或应用本身的错误。
例如:在我们请求一个不存在的URL链接时,会发出一个404 Not Found错误,如下图所示:
当发生错误时,向用户显示我们自定义的出错页面时,我们可以使用错误处理器。
错误处理器是一个函数,类似视图函数的函数,当发生某类错误时,返回一个传递了正在处理的错误的实例响应。
注册错误处理器
在使用错误处理器时,需要先注册错误处理器,注册错误处理器有两种方法:使用errorhandler装饰函数注册、使用register_error_handler()来注册 ,示例代码如下:
#使用装饰器函数注册
@app.errorhandler(werkzeug.exceptions.BadRequest) #传递子类BadRequest
#@app.errorhandler(400) #或传递标准HTTP代码
def handle_bad_request(e):
return '错误请求', 400 #返回出错代码400
#使用register_error_handler()注册
def handle_bad_request(e):
return 'bad request!', 400 #返回出错代码400
app.register_error_handler(400, handle_bad_request)
在使用errorhandler装饰器函数注册时,需要传入werkzeug.exceptions.HTTPException的子类,例如BadRequest或者传递标准HTTP代码,如400,在返回响应时需要设置出错代码。
自定义错误页面
为了更能告诉用户错误信息,我们可以自定义错误页面,首先注册一个错误处理器器,再abort()函数,该函数可以中止请求,产生HTTP错误。Flask程序示例代码如下:
import werkzeug
from flask import Flask, abort
app=Flask(__name__)
@app.errorhandler(400)
def handle_bad_request(e):
return '错误请求', 400 #返回错误信息
@app.route('/')
def hello_world():
abort(400) #使用abort()函数,传递400HTTP代码
if __name__ == '__main__':
app.run()
启动Flask程序,访问http://127.0.0.1:5000/时,网页会显示错误请求。
除了上面返回错误信息的数据格式,我们可以将错误信息以JSON的格式来返回,示例代码如下:
from flask import Flask, abort,jsonify
app=Flask(__name__)
@app.errorhandler(404) #注册404错误处理器
def resource_not_found(e):
return jsonify(error=str(e)), 404 #使用jsonify()方法接收错误对象e,并传入错误HTML代码404
@app.route('/')
def hello_world():
abort(404,description="Resource not found") #抛出错误处理器错误信息
if __name__ == '__main__':
app.run(debug=True)
启动Flask程序,访问http://127.0.0.1:5000/时,网页会显示如下内容:
{
"error": "404 Not Found: Resource not found"
}
自定义错误处理器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程序示例代码如下:
import werkzeug
from flask import Flask, abort, render_template
app=Flask(__name__)
class InsufficientStorage(werkzeug.exceptions.HTTPException): #自定义HTTP错误子类
code=1000
description = 'Not enough storage space.'
def handle_1000(e):
return '服务器无法存储完成请求所必须的内容',1000 #返回错误信息及HTTP代码
app.register_error_handler(InsufficientStorage, handle_1000) #注册错误处理器
@app.route('/')
def hello_world():
raise InsufficientStorage() #抛出错误处理器错误信息
if __name__ == '__main__':
app.run(debug=True)
这里我们创建了名为InsufficientStorage的子类,子类里面的内容可以是随意的,再创建一个名为handle_1000()的函数,该函数返回错误请求和HTTP代码。最后使用register_error_handler()方法注册错误处理器——InsufficientStorage子类和handle_507。
启动Flask程序,访问http://127.0.0.1:5000/,如下图所示:
通用错误处理器
通用错误处理器就是把HTTP出错信息转换为JSON并展示在网页中,示例代码如下所示:
import werkzeug
from flask import Flask, abort, render_template
from flask import json
from werkzeug.exceptions import HTTPException
app=Flask(__name__)
@app.errorhandler(HTTPException) #注册错误处理器
def handle_exception(e): #错误处理器函数传入错误对象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
@app.route('/')
def hello_world():
abort(501) #使用abort()传入501错误代码
if __name__ == '__main__':
app.run(debug=True)
首先使用errorhandler装饰器注册错误处理器,并定义错误处理器函数接收错误对象e,根据错误对象e来编辑返回错误响应内容。
启动Flask程序,访问http://127.0.0.1:5000/,如下图所示:
好了,Flask框架——应用错误处理就学到这里了,感谢观看,下篇文章我们继续学习Flask框架——Bootstrap-Flask使用。
公众号:白巧克力LIN
该公众号发布Python、数据库、Linux、Flask、自动化测试、Git等相关文章!
网友评论