Flask应用错误处理
Flask 应用错误处理
应用出错,服务器出错。或早或晚,你会遇到产品出错。即使你的代码是百分百正确, 还是会时常看见出错。为什么?因为其他相关东西会出错。以下是一些在代码完全正确的 条件下服务器出错的情况:
- 客户端已经中断了请求,但应用还在读取数据。
- 数据库已经过载,无法处理查询。
- 文件系统没有空间。
- 硬盘完蛋了。
- 后台服务过载。
- 使用的库出现程序错误。
- 服务器与另一个系统的网络连接出错。
以上只是你会遇到的问题的一小部分。那么如何处理这些问题呢?如果你的应用运行 在生产环境下,那么缺省情况下 Flask 会显示一个简单的出错页面,并把出错情况 记录到 logger
。
但可做的还不只这些,下面介绍一些更好的出错处理方法。
错误日志工具
当足够多的用户触发了错误时,发送关于出错信息的邮件,即使仅包含严重错误的邮件也会是一场灾难。更不用提从来不会去看的日志文件了。 因此,推荐使用 Sentry 来处理应用错误。它可 以在一个开源项目 on GitHub 中获得, 也可以在 hosted version 中免费试用。 Sentry 统计重复错误,捕获堆栈数据和本地变量用于排错,并在发生新的或者指定频度的错误时发送电子邮件。
Sentry顾名思议,翻译过来是哨兵的意思。
它可以监控我们在生产环境中项目的运行状态,一旦某段代码运行报错,或者异常,会第一时间把报错的
路由
,异常文件
,请求方式
等一些非常详细的信息以消息或者邮件给我们,让我们第一时间知道:程序出错了
,继而从Sentry
给出的详细的错误信息中瞬间找到需要处理的代码,尽快把Bug
修复。Sentry是一个实时的事件日志和聚合平台。
Sentry 可以帮助你将程序的所有 exception 自动记录下来,处理 exception 是每个程序的必要部分,有利于我们开发。
如果试用 Sentry 官方提供的服务是需要收费的,不过可以免费试用,当然最好还是自己搭建
Sentry
:文档 自行搭建当然就不收费啦。
要使用 Sentry 需要安装带有 flask 依赖的 raven 客户端:
$ pip install raven[flask]
(venv) E:\Flask\myproject>pip install raven[flask]
Collecting raven[flask]
Downloading https://files.pythonhosted.org/packages/11/3a/b3e46b279b8bdd9eb55857d0e95044cad31732c80f628bb75e1e9e881a32
/raven-6.9.0-py2.py3-none-any.whl (287kB)
100% |████████████████████████████████| 296kB 4.3kB/s
Requirement already satisfied: Flask>=0.8; extra == "flask" in e:\flask\myproject\venv\lib\site-packages (from raven[fla
sk]) (1.0.2)
Collecting blinker>=1.1; extra == "flask" (from raven[flask])
Downloading https://files.pythonhosted.org/packages/1b/51/e2a9f3b757eb802f61dc1f2b09c8c99f6eb01cf06416c0671253536517b6
/blinker-1.4.tar.gz (111kB)
100% |████████████████████████████████| 112kB 8.7kB/s
Requirement already satisfied: Jinja2>=2.10 in e:\flask\myproject\venv\lib\site-packages (from Flask>=0.8; extra == "fla
sk"->raven[flask]) (2.10)
Requirement already satisfied: itsdangerous>=0.24 in e:\flask\myproject\venv\lib\site-packages (from Flask>=0.8; extra =
= "flask"->raven[flask]) (0.24)
Requirement already satisfied: click>=5.1 in e:\flask\myproject\venv\lib\site-packages (from Flask>=0.8; extra == "flask
"->raven[flask]) (6.7)
Requirement already satisfied: Werkzeug>=0.14 in e:\flask\myproject\venv\lib\site-packages (from Flask>=0.8; extra == "f
lask"->raven[flask]) (0.14.1)
Requirement already satisfied: MarkupSafe>=0.23 in e:\flask\myproject\venv\lib\site-packages (from Jinja2>=2.10->Flask>=
0.8; extra == "flask"->raven[flask]) (1.0)
Installing collected packages: blinker, raven
Running setup.py install for blinker ... done
Successfully installed blinker-1.4 raven-6.9.0
把下面内容加入 Flask 应用:
from raven.contrib.flask import Sentry
sentry = Sentry(app, dsn='YOUR_DSN_HERE')
或者,如果使用了工厂,那么可以在稍后初始化:
from raven.contrib.flask import Sentry
sentry = Sentry(dsn='YOUR_DSN_HERE')
def create_app():
app = Flask(__name__)
sentry.init_app(app)
...
return app
YOUR_DSN_HERE 需要被替换为在 Sentry 安装时获得的 DSN 值。
注:关于DSN值,详情可参考Sentry自动化异常提醒一文。
简单的说就是你安装Sentry后,配置文件中 dsn
就在我们看的文档下方,每个用户的 dsn 都是唯一的,在你的项目中配置了 dsn ,Sentry 就能监控你的项目。
之后,服务信息会自动向 Sentry 报告,你就可以接收到出错通知。
错误处理
当错误发生时,你可能想要向用户显示自定义的出错页面。注册出错处理器来做到这点。
一个出错处理器是一个返回响应的普通视图函数。
但是不同之在于它不是用于路由的 ,而是用于一个异常或者当尝试处理请求时抛出 HTTP 状态码。
注册
通过使用 errorhandler()
装饰函数来注册或者稍后使用 register_error_handler()
来注册。 记得当返回响应的时候设置出错代码:
@app.errorhandler(werkzeug.exceptions.BadRequest)
def handle_bad_request(e):
return 'bad request!', 400
# or, without the decorator
app.register_error_handler(400, handle_bad_request)
当注册时, werkzeug.exceptions.HTTPException
的子类,如 BadRequest
,和它们的 HTTP 代码是可替换的。 ( BadRequest.code == 400
)
因为 Werkzeug 无法识别非标准 HTTP 代码,因此它们不能被注册。替代地,使用适当的代码定义一个 HTTPException
子类,注册并抛出异常类:
class InsufficientStorage(werkzeug.exceptions.HTTPException):
code = 507
description = 'Not enough storage space.'
app.register_error_handler(InsuffcientStorage, handle_507)
raise InsufficientStorage()
出错处理器可被用于任何异常类的注册,除了 HTTPException
子类或者 HTTP 状态码。 出错处理器可被用于特定类的注册,也可用于一个父类的所有子类的注册。
处理
在处理请求时,当 Flask 捕捉到一个异常时,它首先根据代码检索。如果该代码没 有注册处理器,它会根据类的继承来查找,确定最合适的注册处理器。如果找不到已 注册的处理器,那么 HTTPException
子类会显示 一个关于代码的通用消息。没有代码的异常会被转化为一个通用的 500 内部服务器 错误。
例如,如果一个 ConnectionRefusedError
的实例被抛出,并且一个出错处 理器注册到 ConnectionError
和 ConnectionRefusedError
,那么 会使用更合适的 ConnectionRefusedError
来处理异常实例,生成响应。
当一个蓝图在处理抛出异常的请求时,在蓝图中注册的出错处理器优先于在应用中全 局注册的出错处理器。但是,蓝图无法处理 404 路由错误,因为 404 发生的路由级 别还不能检测到蓝图。
日志
如何记录异常,比如向管理者发送邮件,参见 日志 。
排除应用错误
应用错误处理 一文所讲的是如何为生产应用设置日志和出错通知。本文要讲的是部署中配置调试的要点和如何使用全功能的 Python 调试器深挖错误。
有疑问时,请手动运行
在生产环境中,配置应用时出错?
如果你可以通过 shell 来访问主机,那么首先请在部署环境中验证是否可以通过 shell 手动运行你的应用。
请确保验证时使用的帐户与配置的相同,这样可以排除用户权限引发的错误。
可以在你的生产服务器上, 使用 Flask 内建的开发服务器,并且设置
debug=True
,这样有助于找到配置问 题。但是,请 只在可控的情况下临时这样做 ,绝不能在生产时使用debug=True
。
使用调试器
为了更深入的挖掘错误,追踪代码的执行, Flask 提供一个开箱即用的调试器(参 见 调试模式 )。如果你需要使用其他 Python 调试器,请注意调试器之 间的干扰问题。在使用你自己的调试器前要做一些参数调整:
debug
- 是否开启调试模式并捕捉异常use_debugger
- 是否使用 Flask 内建的调试器use_reloader
- 出现异常后是否重载或者派生进程
debug
必须设置为 True (即必须捕获异常),另两个随便。
如果你正在使用 Aptana 或 Eclipse 排错,那么 use_debugger
和 use_reloader
都必须设置为 False 。
一个有用的配置模式如下(当然要根据你的应用调整缩进):
FLASK:
DEBUG: True
DEBUG_WITH_APTANA: True
然后,在应用入口( main.py ),修改如下:
if __name__ == "__main__":
# To allow aptana to receive errors, set use_debugger=False
app = create_app(config="config.yaml")
if app.debug: use_debugger = True
try:
# Disable Flask's debugger if external debugger is requested
use_debugger = not(app.config.get('DEBUG_WITH_APTANA'))
except:
pass
app.run(use_debugger=use_debugger, debug=app.debug,
use_reloader=use_debugger, host='0.0.0.0')
参考
- 本文大部分引用自Flask中文文档
我在它的基础上加入了一些命令的反馈和一些插件更具体的描述等。
Flask应用错误处理的更多相关文章
- Flask的错误日志处理和|ORM操作
flask有个很人性化的处理就是 你的错误的输出是可以通过错误日志来自定义 ,让你输入的错误不再是“大黄页”, 通过 errorhandler()来装饰函数之后你的所有的输入错误的函数你都会进入这个 ...
- 关于flask的错误:ImportError: cannot import name 'Flask'
刚开始接触flask,新创建后不能运行,报错如下图: 导致该错误有两种可能,没安装flask:文件名为flask. 可尝试如下两种方法解决: 方法一:若没安装过flask,则进入cmd,输入pip i ...
- python3.8安装flask出现错误“ModuleNotFoundError: No module named '_ctypes'”
本想在CentOS下配置flask+nginx+uwsgi环境,结果安装最基础的flask包都出了问题...以下是我的环境: 服务器:阿里云ECS CentOS7 python版本:3.8.0 问题描 ...
- flask中错误使用flask.redirect('/path')导致的框架奇怪错误
我在首页的位置使用了如下代码: import flask @page_index.route('/') def index(): flask.redirect('/pythoncgi/') 结果站点出 ...
- Flask进阶
Threading.local 作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离). 应用: flask上下文管理中的local中比这更高级,为协程. DBUtils ...
- Flask源码剖析详解
1. 前言 本文将基于flask 0.1版本(git checkout 8605cc3)来分析flask的实现,试图理清flask中的一些概念,加深读者对flask的理解,提高对flask的认识.从而 ...
- Flask:初次使用Blueprints
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2,Eclipse Oxygen.1a Release (4.7.1a),PyDev 6.3.2 本文为记录自己第一次使用 ...
- Flask (七) 部署
阿里云部署Flask项目 部署Flask项目和部署Django项目基本一致,我们也使用uwsgi+nginx 我们在部署Django项目基础上部署Flask项目 1, 将uwsgi.ini ...
- Flask中本地栈的使用
4种上下文变量 承接上一篇内容.当一个请求到来时,除了request被封装成全局变量之外,还有三个变量也是同样被封装成全局变量,那就是current_app.g.session.上面4个变量之所以能够 ...
随机推荐
- 常用的npm指令总结
一.安装指令,通常是全局安装 npm install <package name> -g 二.移除全局安装包 npm uninstall <package name> -g 三 ...
- Spring boot CommandLineRunner接口使用例子
前言 Spring boot的CommandLineRunner接口主要用于实现在应用初始化后,去执行一段代码块逻辑,这段初始化代码在整个应用生命周期内只会执行一次. 如何使用CommandLineR ...
- ACM学习<一>
c++指针|指针入门 什么是指针? 其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据.这是一个非常重要的概念,有很多 ...
- 从零开始学 Web 之 Vue.js(一)Vue.js概述,基本结构,指令,事件修饰符,样式
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- MongoDB 常用的几大GUI工具
MongoDB 常用的几大GUI工具 MongoDBCompass (官方的连接工具),免费的,界面简洁,不支持 sql 查询,支持性能监控.支持在三大平台 Windows .Mac .Linux 上 ...
- k8s升级,HA集群1.12.0~HA集群1.13.2
k8s升级,此次升级是1.12.0 至1.13.2 准备 # 首先升级master节点的基础组件kubeadm.kubelet.kubectl apt policy kubeadm 找到相应的版本,如 ...
- 自定义Fiddler插件一
上个月自定义了一个Fiddler的插件,可以根据请求生成接口自动化测试的RF和Python代码,这样测试人员只需要手动操作页面用Fiddler抓取报文,就可以直接生成RF.Python代码,然后只需要 ...
- 在Web.config或App.config中的添加自定义配置 <转>
.Net中的System.Configuration命名空间为我们在web.config或者app.config中自定义配置提供了完美的支持.最近看到一些项目中还在自定义xml文件做程序的配置 ...
- [日常] C语言中指针变量
CPU 访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址.编译和链接过程的一项重要任务就是找到这些名称所对应的 ...
- 【22】访问者模式(Visitor Pattern)
一.引言 在这篇博文中,我将为大家分享我对访问者模式的理解. 二.访问者模式介绍 2.1 访问者模式的定义 访问者模式是封装一些施加于某种数据结构之上的操作.一旦这些操作需要修改的话,接受这个操作的数 ...