应用程序错误 — Flask 文档
应用程序错误
0.3 版中的新功能。
应用程序失败,服务器失败。 迟早你会在生产中看到异常。 即使您的代码是 100% c 正确,您仍然会不时看到异常。 为什么? 因为其他涉及的一切都会失败。 以下是一些完美的代码可能导致服务器错误的情况:
- 客户端提前终止请求,应用程序仍在读取传入的数据
- 数据库服务器过载,无法处理查询
- 文件系统已满
- 硬盘坏了
- 后端服务器过载
- 您正在使用的库中的编程错误
- 服务器到另一个系统的网络连接失败
这只是您可能面临的一小部分问题。 那么我们如何处理这样的问题呢? 默认情况下,如果您的应用程序在生产模式下运行,Flask 将为您显示一个非常简单的页面,并将异常记录到 logger
。
但是你可以做更多的事情,我们将介绍一些更好的设置来处理错误。
错误记录工具
发送错误邮件,即使只是针对关键邮件,如果有足够多的用户遇到错误并且通常从不查看日志文件,也会变得不堪重负。 这就是我们推荐使用 Sentry 来处理应用程序错误的原因。 它可以作为开源项目 在 GitHub 上使用,也可以作为 托管版本 使用,您可以免费试用。 Sentry 聚合重复错误,捕获完整的堆栈跟踪和局部变量以进行调试,并根据新错误或频率阈值向您发送邮件。
要使用 Sentry,您需要安装带有额外 flask 依赖项的 sentry-sdk 客户端:
然后将其添加到您的 Flask 应用程序中:
YOUR_DSN_HERE 值需要替换为您从 Sentry 安装中获得的 DSN 值。
安装后,导致内部服务器错误的故障会自动报告给 Sentry,您可以从那里收到错误通知。
后续内容如下:
- Sentry 还支持以类似的方式从您的工作队列(RQ、Celery)中捕获错误。 有关更多信息,请参阅 Python SDK 文档 。
- 哨兵入门
- Flask 特定文档。
错误处理程序
您可能希望在发生错误时向用户显示自定义错误页面。 这可以通过注册错误处理程序来完成。
错误处理程序是一个返回响应的普通视图函数,但它不是为路由注册,而是为尝试处理请求时将引发的异常或 HTTP 状态代码注册。
注册
通过用 errorhandler()
修饰函数来注册处理程序。 或者稍后使用register_error_handler()
注册该函数。 请记住在返回响应时设置错误代码。
werkzeug.exceptions.HTTPException
子类如 BadRequest
及其 HTTP 代码在注册处理程序时是可互换的。 (BadRequest.code == 400
)
非标准 HTTP 代码无法通过代码注册,因为 Werkzeug 不知道它们。 相反,使用适当的代码定义 HTTPException
的子类并注册和引发该异常类。
可以为任何异常类注册处理程序,而不仅仅是 HTTPException
子类或 HTTP 状态代码。 可以为特定类或父类的所有子类注册处理程序。
处理
当 Flask 在处理请求时捕获异常时,首先通过代码查找异常。 如果没有为代码注册处理程序,则通过其类层次结构查找; 选择最具体的处理程序。 如果未注册处理程序,HTTPException
子类会显示有关其代码的通用消息,而其他异常将转换为通用 500 内部服务器错误。
例如,如果引发了 ConnectionRefusedError
的实例,并且为 ConnectionError
和 ConnectionRefusedError
注册了一个处理程序,则使用以下命令调用更具体的 ConnectionRefusedError
处理程序生成响应的异常实例。
蓝图上注册的处理程序优先于应用程序上全局注册的处理程序,假设蓝图正在处理引发异常的请求。 但是,蓝图无法处理 404 路由错误,因为 404 发生在路由级别,然后才能确定蓝图。
通用异常处理程序
可以为非常通用的基类(例如 HTTPException
甚至 Exception
)注册错误处理程序。 但是,请注意,这些捕获量会超出您的预期。
例如,HTTPException
的错误处理程序可能有助于将默认 HTML 错误页面转换为 JSON。 但是,此处理程序将触发您不会直接引起的事情,例如路由期间的 404 和 405 错误。 请务必仔细制作处理程序,以免丢失有关 HTTP 错误的信息。
Exception
的错误处理程序对于更改所有错误(甚至是未处理的错误)呈现给用户的方式似乎很有用。 但是,这类似于在 Python 中执行 except Exception:
,它将捕获 all 否则未处理的错误,包括所有 HTTP 状态代码。 在大多数情况下,为更具体的异常注册处理程序会更安全。 由于 HTTPException
实例是有效的 WSGI 响应,您也可以直接传递它们。
错误处理程序仍然尊重异常类层次结构。 如果同时为 HTTPException
和 Exception
注册处理程序,Exception
处理程序将不会处理 HTTPException
子类,因为 HTTPException
处理程序更多具体的。
未处理的异常
当没有为异常注册错误处理程序时,将返回 500 Internal Server Error。 有关此行为的信息,请参阅 flask.Flask.handle_exception()
。
如果为 InternalServerError
注册了错误处理程序,则将调用该处理程序。 从 Flask 1.1.0 开始,此错误处理程序将始终传递一个 InternalServerError
实例,而不是原始未处理的错误。 原始错误可用作 e.original_exception
。 在 Werkzeug 1.0.0 之前,这个属性只会在未处理的错误期间存在,为了兼容性,使用 getattr
来访问它。
调试应用程序错误
对于生产应用程序,如 应用程序错误 中所述,使用日志记录和通知配置您的应用程序。 本节提供调试部署配置和使用全功能 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。
一个可能有用的配置模式是在您的 config.yaml 中设置以下内容(当然,根据您的应用程序更改块):
然后在您的应用程序的入口点 (main.py) 中,您可以拥有如下内容: