一、错误处理器
在 Flask 中发生错误时,会返回一个相应的 HTTP 状态码 。状态码 400-499 表示客户端的请求数据或者与之相关的错误。状态码 500-599 表示服务器或者应用本身的错误。
当错误发生时,你可能想要向用户显示自定义的出错页面。注册出错处理器可以 做到这点。
一个出错处理器是一个函数,当发生某类错误时返回一个响应。类似于一个视图 函数,当请求 URL 匹配时返回一个响应。它传递了正在处理的错误的实例,基本 上是一个 HTTPException 。
响应的状态代码不会设置为处理器的代码。请确保从处理器返回一个响应时提供 适当的 HTTP 状态码。
1.1 原始的错误堆栈
@app.route('/')
def hello_world():
# 模拟错误
num = 1 / 0
return 'Hello World!'
页面上的错误
后台的错误
但是这样的错误,尤其是前端的错误,给人的感觉是不太友好。
二、注册
通过使用 errorhandler()
装饰函数来注册或者稍后使用 register_error_handler()
来注册。记得当返回响应的时候设置出错代码。
@app.route('/')
@app.errorhandler(werkzeug.exceptions.BadRequest)
def hello_world(): # put application's code here
# 这里直接返回了一个字符串,给浏览器
try:
num = 1 / 0
except Exception as e:
return '发生了异常!', 500
当注册时, werkzeug.exceptions.HTTPException
的子类,如 BadRequest
,和它们的 HTTP 代码是可替换的。( BadRequest.code == 400 )
因为 Werkzeug 无法识别非标准 HTTP 代码,所以它们不能被注册。
相反,使用 适当的代码定义一个 HTTPException
子类, 注册并抛出异常类。
class MyException(werkzeug.exceptions.HTTPException):
code = 5000
description = '除数不能为0'
# 路由
@app.route('/')
def hello_world(): # put application's code here
# 这里直接返回了一个字符串,给浏览器
try:
num = 1 / 0
except Exception as e:
raise MyException
三、处理
在构建 Flask 应用时,您 会 遇到异常。如果在处理请求时(且您没有注册 错误处理器),你的代码中断了,那么将默认返回“ 500 内部服务器错误” ( InternalServerError
)。同样,如果请求被发送到未注册的路由,则会产生 “ 404 未找到” ( NotFound
)错误。如果路由接收到被禁止的请求方法,则会产生“ 405 方法被禁止” (MethodNotAllowed
) 。Flask 默认提供这些 HTTPException
的子类。
Flask 使您能够注册 Werkzeug 提供的任意 HTTP 异常。但是,默认的 HTTP 异 常返回简单的异常页。您可能希望在发生错误时向用户显示自定义错误页面。可 以通过注册错误处理器来完成。
在处理请求时,当 Flask 捕捉到一个异常时,它首先根据代码检索。如果该代码 没有注册处理器,它会根据类的继承来查找,确定最合适的注册处理器。如果找 不到已注册的处理器,那么 HTTPException
子 类会显示一个关于代码的通用消息。没有代码的异常会被转化为一个通用的 “ 500 内部服务器错误”。
例如,如果一个 ConnectionRefusedError
的实例被抛出,并且一个出错 处理器注册到 ConnectionError
和 ConnectionRefusedError
, 那么会使用更合适的 ConnectionRefusedError
来处理异常实例,生成响应。
当一个蓝图在处理抛出异常的请求时,在蓝图中注册的出错处理器优先于在应用 中全局注册的出错处理器。但是,蓝图无法处理 404 路由错误,因为 404 发生 的路由级别还不能检测到蓝图。
四、通用异常处理器
可以为非常通用的基类注册异常处理器,例如 HTTPException 基类或者甚至 Exception 基类。但是,请注意,这样会捕捉到超出你预期的异常。
例如,基于 HTTPException 的异常处理器对于把缺省的 HTML 出错页面转换 为 JSON 非常有用,但是这个处理器会触发不由你直接产生的东西,如路由过程 中产生的 404 和 405 错误。请仔细制作你的处理器,确保不会丢失关于 HTTP 错误的信息。
# 定义一个全局异常处理函数
@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
@app.route("/exe")
def exec():
try:
num = 1 / 0
except Exception as e:
# 有问题就abort
abort(500)
这样页面上就会有统一的json错误处理。
这里只是实现一种方式,在真正的生产中,错误信息一定会定义的更加细致。
当然,在模板技术中,还可以直接返回500错误到模板中
@app.route("/exe")
def exec():
try:
num = 1 / 0
except Exception as e:
return render_template("500.html", e=e), 500
五、自定义错误页面
有时在构建 Flask 应用时,您可能希望产生一个 HTTPException ,向用户发出信号,提示请求有 问题。幸运的是,Flask 附带了一个方便的来自 werkzeug 的 abort()
函数,可以中止请求,产生 HTTP 错误。它还提供一个带 有基本描述的朴素的黑白页面。
依据错误代码,用户可以或多或少,知道一些错误。
考虑下面的代码,我们可能有一个用户配置文件路由,如果用户未能传递用户名, 我们可以引发“ 400 错误请求”。如果用户传递了用户名,但是我们找不到它, 我们引发“ 404 页面未找到”。
@app.errorhandler(404)
def page_not_found(e):
# 等出现404时,就去404页面
return render_template('404.html'), 404
@app.route("/notfound")
def notfound():
abort(404)
当使用 应用工厂 时:
def page_not_found(e):
return render_template('404.html'), 404
def create_app(config_filename):
app = Flask(__name__)
app.register_error_handler(404, page_not_found)
return app
当使用 使用蓝图进行应用模块化 时:
from flask import Blueprint
blog = Blueprint('blog', __name__)
# as a decorator
@blog.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
# or with register_error_handler
blog.register_error_handler(500, internal_server_error)
在 使用蓝图进行应用模块化 中,大多数错误处理器会按预期工作,但是处理 404 和 405 错误的处理器比较特殊,要小心。这些错误处理器只有从适当的 raise 语句调用时或者在另一个蓝印在视图函数中调用 abort 时才会调用。相反, 例如非法 URL 访问时,则不会调用。
这是因为蓝印不“拥有”一定的 URL 空间,所以应用实例无法知道非法 URL 访 问应当调用哪个蓝印的错误处理器。如果需要基于 URL 前缀配置不同的处理策略, 那么可以使用 rquest 代理对象在应用层面进行配置。
原文始发于微信公众号(Python之家):Flask-11-应用错误处理
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/198254.html