调试在Gunicorn中运行的Flask应用

81 投票
7 回答
94602 浏览
提问于 2025-04-17 10:45

我正在用nginx/gunicorn和Flask为我的应用程序搭建一个新的开发平台。

从运维的角度来看,一切都运作得很好——我遇到的问题是调试Flask层。当我的代码出现错误时,浏览器只会收到一个500错误,而控制台或日志中什么也看不到。

我尝试了很多不同的配置和选项……我想我一定漏掉了什么明显的东西。

这是我的gunicorn配置文件:

import os

bind = '127.0.0.1:8002'
workers = 3
backlog = 2048
worker_class = "sync"
debug = True
proc_name = 'gunicorn.proc'
pidfile = '/tmp/gunicorn.pid'
logfile = '/var/log/gunicorn/debug.log'
loglevel = 'debug'

这是一些出错的Flask代码示例——testserver.py:

from flask import Flask
from flask import render_template_string
from werkzeug.contrib.fixers import ProxyFix

app = Flask(__name__)

@app.route('/')
def index():
    n = 1/0
    return "DIV/0 worked!"

最后,这是用gunicorn运行Flask应用的命令:

gunicorn -c gunicorn.conf.py testserver:app

谢谢大家!

7 个回答

24

对于Heroku用户,有一个比Nick建议的创建bin/web脚本更简单的解决方案。

如果你想在开发过程中调试你的应用,不用输入foreman start,只需使用foreman run python app.py就可以了。

93

我试过的解决方案对我没用。

Gunicorn 是一种预先分叉的环境,而显然 Flask 的调试器在分叉环境中无法工作

注意

尽管交互式调试器在分叉环境中无法使用(这使得在生产服务器上几乎不可能使用)[...]

即使你设置了 app.debug = True,如果你用 gunicorn testserver:app 运行,仍然只会看到一个空白页面,上面写着 内部服务器错误。使用 gunicorn 最好的办法是用 gunicorn --debug testserver:app 运行。这样你可以看到错误信息和跟踪信息。但这只是你在终端看到的文本跟踪,而不是 Flask 的调试器。

如果你在 testserver.py 中添加 if __name__ ... 部分,然后用 python testserver.py 启动服务器,就能得到 Flask 的调试器。换句话说,如果你想使用 Flask 的调试器,就不要在开发中使用 gunicorn。

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

if __name__ == '__main__':
    app.run()

## 给 Heroku 用户的提示: 我个人还是喜欢用 `foreman start`,而不是 `python testserver.py`,因为 [它为我设置了所有的环境变量](https://devcenter.heroku.com/articles/config-vars#using-foreman)。要让这个工作:

Procfile 的内容

web: bin/web

bin/web 的内容,这个文件相对于项目根目录

#!/bin/sh

if [ "$FLASK_ENV" == "development" ]; then
        python app.py
else
        gunicorn app:app -w 3
fi

在开发中,创建一个相对于项目根目录的 .env 文件,内容如下(文档 在这里

FLASK_ENV=development
DEBUG=True

另外,别忘了在 testserver.py 中把 app.config['DEBUG']... 这一行改成在生产环境中不会让 Flask 以调试模式运行的内容。

app.config['DEBUG'] = os.environ.get('DEBUG', False)
53

Flask的配置和gunicorn的配置是完全分开的。根据Flask关于配置文件的说明,一个好的解决办法是把我的代码改成这样:

app = Flask(__name__)
app.config.from_pyfile('config.py')

在config.py文件中:

DEBUG = True

撰写回答