Flask 应用错误处理

应用出错,服务器出错。或早或晚,你会遇到产品出错。即使你的代码是百分百正确, 还是会时常看见出错。为什么?因为其他相关东西会出错。以下是一些在代码完全正确的 条件下服务器出错的情况:

  • 客户端已经中断了请求,但应用还在读取数据。
  • 数据库已经过载,无法处理查询。
  • 文件系统没有空间。
  • 硬盘完蛋了。
  • 后台服务过载。
  • 使用的库出现程序错误。
  • 服务器与另一个系统的网络连接出错。

以上只是你会遇到的问题的一小部分。那么如何处理这些问题呢?如果你的应用运行 在生产环境下,那么缺省情况下 Flask 会显示一个简单的出错页面,并把出错情况 记录到 logger

但可做的还不只这些,下面介绍一些更好的出错处理方法。

错误日志工具

当足够多的用户触发了错误时,发送关于出错信息的邮件,即使仅包含严重错误的邮件也会是一场灾难。更不用提从来不会去看的日志文件了。 因此,推荐使用 Sentry 来处理应用错误。它可 以在一个开源项目 on GitHub 中获得, 也可以在 hosted version 中免费试用。 Sentry 统计重复错误,捕获堆栈数据和本地变量用于排错,并在发生新的或者指定频度的错误时发送电子邮件。

  • Sentry顾名思议,翻译过来是哨兵的意思。

  • 它可以监控我们在生产环境中项目的运行状态,一旦某段代码运行报错,或者异常,会第一时间把报错的 路由异常文件请求方式 等一些非常详细的信息以消息或者邮件给我们,让我们第一时间知道:程序出错了,继而从 Sentry 给出的详细的错误信息中瞬间找到需要处理的代码,尽快把 Bug 修复。

  • Sentry是一个实时的事件日志和聚合平台。

  • Sentry 可以帮助你将程序的所有 exception 自动记录下来,处理 exception 是每个程序的必要部分,有利于我们开发。

  • 如果试用 Sentry 官方提供的服务是需要收费的,不过可以免费试用,当然最好还是自己搭建 Sentry文档 自行搭建当然就不收费啦。

  • 官网安装和使用参考

  • Docker 安装 HerePython 安装 Here

要使用 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 的实例被抛出,并且一个出错处 理器注册到 ConnectionErrorConnectionRefusedError ,那么 会使用更合适的 ConnectionRefusedError 来处理异常实例,生成响应。

当一个蓝图在处理抛出异常的请求时,在蓝图中注册的出错处理器优先于在应用中全 局注册的出错处理器。但是,蓝图无法处理 404 路由错误,因为 404 发生的路由级 别还不能检测到蓝图。

日志

如何记录异常,比如向管理者发送邮件,参见 日志

排除应用错误

应用错误处理 一文所讲的是如何为生产应用设置日志和出错通知。本文要讲的是部署中配置调试的要点和如何使用全功能的 Python 调试器深挖错误。

有疑问时,请手动运行

在生产环境中,配置应用时出错?

  • 如果你可以通过 shell 来访问主机,那么首先请在部署环境中验证是否可以通过 shell 手动运行你的应用。

  • 请确保验证时使用的帐户与配置的相同,这样可以排除用户权限引发的错误。

  • 可以在你的生产服务器上, 使用 Flask 内建的开发服务器,并且设置 debug=True ,这样有助于找到配置问 题。但是,请 只在可控的情况下临时这样做 ,绝不能在生产时使用 debug=True

使用调试器

为了更深入的挖掘错误,追踪代码的执行, Flask 提供一个开箱即用的调试器(参 见 调试模式 )。如果你需要使用其他 Python 调试器,请注意调试器之 间的干扰问题。在使用你自己的调试器前要做一些参数调整:

  • debug - 是否开启调试模式并捕捉异常
  • use_debugger - 是否使用 Flask 内建的调试器
  • use_reloader - 出现异常后是否重载或者派生进程

debug 必须设置为 True (即必须捕获异常),另两个随便。

如果你正在使用 Aptana 或 Eclipse 排错,那么 use_debuggeruse_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应用错误处理的更多相关文章

  1. Flask的错误日志处理和|ORM操作

    flask有个很人性化的处理就是 你的错误的输出是可以通过错误日志来自定义  ,让你输入的错误不再是“大黄页”, 通过 errorhandler()来装饰函数之后你的所有的输入错误的函数你都会进入这个 ...

  2. 关于flask的错误:ImportError: cannot import name 'Flask'

    刚开始接触flask,新创建后不能运行,报错如下图: 导致该错误有两种可能,没安装flask:文件名为flask. 可尝试如下两种方法解决: 方法一:若没安装过flask,则进入cmd,输入pip i ...

  3. python3.8安装flask出现错误“ModuleNotFoundError: No module named '_ctypes'”

    本想在CentOS下配置flask+nginx+uwsgi环境,结果安装最基础的flask包都出了问题...以下是我的环境: 服务器:阿里云ECS CentOS7 python版本:3.8.0 问题描 ...

  4. flask中错误使用flask.redirect('/path')导致的框架奇怪错误

    我在首页的位置使用了如下代码: import flask @page_index.route('/') def index(): flask.redirect('/pythoncgi/') 结果站点出 ...

  5. Flask进阶

    Threading.local 作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离). 应用: flask上下文管理中的local中比这更高级,为协程. DBUtils ...

  6. Flask源码剖析详解

    1. 前言 本文将基于flask 0.1版本(git checkout 8605cc3)来分析flask的实现,试图理清flask中的一些概念,加深读者对flask的理解,提高对flask的认识.从而 ...

  7. Flask:初次使用Blueprints

    Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2,Eclipse Oxygen.1a Release (4.7.1a),PyDev 6.3.2 本文为记录自己第一次使用 ...

  8. Flask (七) 部署

    阿里云部署Flask项目   部署Flask项目和部署Django项目基本一致,我们也使用uwsgi+nginx   我们在部署Django项目基础上部署Flask项目   1, 将uwsgi.ini ...

  9. Flask中本地栈的使用

    4种上下文变量 承接上一篇内容.当一个请求到来时,除了request被封装成全局变量之外,还有三个变量也是同样被封装成全局变量,那就是current_app.g.session.上面4个变量之所以能够 ...

随机推荐

  1. JavaSE-关键字final

    final修饰数据: final修饰基本数据类型,使数值恒定不变,修饰对象引用,final使引用恒定不变 final修饰的成员变量必须要被初识化 final可以修饰方法中的参数列表,被修饰的参数无法在 ...

  2. 关于 Nginx 配置 WebSocket 400 问题

    今天把项目升级了 asp.net core 到 2.1 的版本,使用了 signalr  的功能,由于阿里云不支持 websocket 协议,所以使用了 nginx 代理方式来解决,后续就报了一个登陆 ...

  3. 堆排序——HeapSort

    基本思想:   图示: (88,85,83,73,72,60,57,48,42,6)   平均时间复杂度: O(NlogN)由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作 ...

  4. 无源码调试smali

    0x01    工具①Android Studio最新版.(用的1.5)②apktool尽量使用最新版的.(反编译本人用baksmali-2.1.3.jar)③smalidea插件.下载地址https ...

  5. Java 8 新特性-菜鸟教程 (9) -Java8 Base64

    Java8 Base64 在Java 8中,Base64编码已经成为Java类库的标准. Java 8 内置了 Base64 编码的编码器和解码器. Base64工具类提供了一套静态方法获取下面三种B ...

  6. kubeadm部署kubernetes-1.12.0 HA集群-ipvs

    一.概述 主要介绍搭建流程及使用注意事项,如果线上使用的话,请务必做好相关测试及压测. 1.基础环境准备 系统:ubuntu TLS 16.04  5台 docker-ce:17.06.2 kubea ...

  7. 记一次升级Tomcat

    总述     JDK都要出12了,而我们项目使用的jdk却仍然还停留在JDK1.6.为了追寻技术的发展的脚步,我这边准备将项目升级到JDK1.8.而作为一个web项目,我们的容器使用的是Tomcat. ...

  8. windows环境下pycharm如何设置Linux编码

    最近写代码一直在windows环境下,写完之后再传到Linux端就会出现代码格式错乱. 解决办法: 在windows端的pycharm代码格式设置为unix and os及可以解决这个问题. 如果你要 ...

  9. EXTJS4 Grid Filter 插件的使用 与后台数据解析------Extjs 查询筛选功能的实现

    先汗一个,一个小功能又踢腾了一天.本来这个带Demo的,但是上面介绍的不是很详细.用的时候问题不大,主要问题在文件导入方面.以为这个插件的使用和其他的不一样. 1.首先是需要引入文件的位置:如图 需要 ...

  10. .NET常用开发工具整理

    版本控制和项目管理工具 VisualSVN和AnkhSVN:两款在Visual Studio中管理Subversion的插件.. NuGet和NuGetPackageExplorer:一组用于自动执行 ...