【问题标题】:Catching a 500 server error in Flask在 Flask 中捕获 500 服务器错误
【发布时间】:2013-02-06 05:58:50
【问题描述】:

我喜欢 Flask 的错误捕捉功能。非常简单:

@app.errorhandler(404)
def pageNotFound(error):
    return "page not found"

像魅力一样工作。但它不适用于 500 错误代码。当出现问题时,我想在代码中引发异常时捕获 Python 错误。这可能吗?

我应该注意,如果我在视图中明确调用return abort(500),那么 500 错误处理程序确实可以工作。因此,这明确适用于 Python 代码失败的情况。

这可能吗?

【问题讨论】:

  • 你能澄清一下你在找什么吗?我不明白您所说的“我想在出现问题时捕获 Python 错误,并在代码中引发异常”是什么意思。你的意思是如果在普通视图中引发 Python 异常,你期望 500 错误处理程序会被自动调用?
  • 这是正确的,如果普通视图中的代码执行诸如将 1 除以 0 或访问 2 元素数组中的第三个元素或执行任何其他引发 Python 异常且未捕获异常的操作,我想要一个特殊的视图方法来运行。用@app.errorhandler(500) 装饰一个函数似乎不起作用。

标签: python flask


【解决方案1】:

它在我身边很好用:

from flask import Flask ,url_for,render_template,request,abort
from  werkzeug.debug import get_current_traceback
app = Flask(__name__)

@app.route('/')
def index():
    try:
        raise Exception("Can't connect to database")
    except Exception,e:
        track= get_current_traceback(skip=1, show_hidden_frames=True,
            ignore_system_exceptions=False)
        track.log()
        abort(500)
    return "index"

@app.errorhandler(500)
def internal_error(error):

    return "500 error"

@app.errorhandler(404)
def not_found(error):
    return "404 error",404

if __name__== "__main__":
    app.run(debug=True)

Flask 不会为您设置错误代码,因此请确保在返回响应时也提供 HTTP 状态代码。

【讨论】:

  • 如果你使用DEBUG=True 它将无法工作(打印堆栈跟踪),它在开发中很舒服。因此,如果您想查看真正的 500 页,请检查 Flask 应用程序是否未在 DEBUG 模式下运行。
  • 我很困惑,你想要 Flask 处理异常还是要客户处理异常?
  • 当然要处理。我的意思是,当你开发时使用调试模式,当你的 500 错误没有漂亮的页面而不是堆栈跟踪时,你可能会有点困惑。
  • 当然,开发的时候可以不加@app.errorhandler(500)
  • 我已经更新了代码,在大多数情况下,我们需要捕获数据库无法连接的异常,然后我们可以打印堆栈跟踪,它还会显示客户 500 错误页面。
【解决方案2】:

您所描述的是,默认情况下,Flask 是如何工作的。我的假设是您正在调试模式下运行,因此在调试屏幕中会向您显示异常。确保调试模式已关闭,然后重试。这是comment directly from the code itself:

在发生异常时启动的默认异常处理 没有被抓住。在调试模式下,将重新引发异常 立即,否则将被记录并处理 500 内部 使用了服务器错误。如果不存在这样的处理程序,则默认为 500 显示内部服务器错误消息。

【讨论】:

  • 如果您尝试关闭调试模式但仍无法正常工作,请发布更多代码。
  • 你是对的,一旦我禁用了调试模式,然后它就起作用了。感谢您指出了这一点。我使用调试模式,以便在开发过程中进行更改时自动重新加载代码。有没有办法在没有调试模式的情况下自动重新加载?
  • 等等,什么?我刚刚再次打开调试,500 错误处理程序仍然工作,我得到自动代码重新加载!再次关闭调试模式意味着 500 处理程序仍然工作并且代码不会重新加载(有意义),但再次打开调试会使 500 处理程序继续工作。这对我来说都很好,但很可疑。
  • 当你打开和关闭调试时,你是真的在重启进程,还是仅仅依靠重新加载?
  • 哦,等等,我笨。原来我在这段时间里实际上有abort(500) 代码。当我关闭它时,我实际上得到了预期的行为,我需要关闭调试模式才能使app.errorhandler 工作。对不起,我觉得浪费你的时间很愚蠢。
【解决方案3】:

这是我的代码片段

@app.route('/')
def index():
    raise Exception("Can't connect to database")


@app.errorhandler(Exception)
def exception_handler(error):
    return "!!!!"  + repr(error)

【讨论】:

  • app.debug 对我不起作用,所以这救了我!谢谢!
  • Thanx :) 它处理了 500 引发的异常(内部服务器错误),但应添加另一个 404 处理,如:app.register_error_handler(404, page_not_found) then : def page_not_found(e): return渲染模板('pageNotFound.html'),404
【解决方案4】:

我对此的解决方案是通过修改配置字典来打开异常传播:

app = Flask(__name__)
...
app.config['PROPAGATE_EXCEPTIONS'] = True

看看这个其他相关问题:Flask app raises a 500 error with no exception

【讨论】:

  • 谢谢!!我把头发扯了下来,最后在我的日志中添加了这行“给我扔了一根骨头”,这样我就可以弄清楚了。我讨厌500个错误!他们为什么不直接输入“错误:发生了什么事”;)
【解决方案5】:

此代码捕获 500 状态代码并获得异常错误

@app.errorhandler(Exception)
def all_exception_handler(e):
    error = str(traceback.format_exc())

【讨论】:

  • 这捕获所有通用错误本身并不是一个好习惯。
【解决方案6】:

问题在于,在代码中,并非所有异常都是HTTPException,但 Flask 默认捕获这些异常并返回通用 500 错误响应(可能包括也可能不包括 @Mark Hildreth 描述的原始错误消息) .因此,使用@app.errorhandler(500) 不会捕获这些错误,因为这发生在 Flask 返回通用 500 错误之前。

您需要有一个通用的errorhandler(Exception),它的工作方式类似于python 中的except Exception:,它可以捕获所有内容。 Flask pallets projects提供了一个很好的解决方案:

from werkzeug.exceptions import HTTPException

@app.errorhandler(Exception)
def handle_exception(e):
    # pass through HTTP errors. You wouldn't want to handle these generically.
    if isinstance(e, HTTPException):
        return e

    # now you're handling non-HTTP exceptions only
    return render_template("500_generic.html", e=e), 500

如果您愿意,也可以返回 JSON,如果您处于调试模式,还可以包含原始错误消息。例如

from flask import jsonify
from werkzeug.exceptions import HTTPException

debug = True  # global variable setting the debug config

@app.errorhandler(Exception)
def handle_exception(e):
    if isinstance(e, HTTPException):
        return e

    res = {'code': 500,
           'errorType': 'Internal Server Error',
           'errorMessage': "Something went really wrong!"}
    if debug:
        res['errorMessage'] = e.message if hasattr(e, 'message') else f'{e}'

    return jsonify(res), 500

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2018-01-27
    • 1970-01-01
    相关资源
    最近更新 更多