为什么运行 Flask dev 服务器会自己运行两次?

我正在使用 酒瓶开发一个网站,在开发过程中,我使用以下文件运行烧瓶:

#!/usr/bin/env python
from datetime import datetime
from app import app
import config


if __name__ == '__main__':
print('################### Restarting @', datetime.utcnow(), '###################')
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0')

当我启动服务器时,或者因为文件已经更新而自动重新启动时,它总是显示两次打印行:

################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################

虽然它不是一个真正的问题(其余的工作正如预期的那样) ,我只是想知道为什么它的行为是这样的?有什么想法吗?

47776 次浏览

Werkzeug 重新加载器生成一个子进程,以便在每次代码更改时重新启动该进程。Werkzeug 是在您调用 app.run()时为 Flask 提供开发服务器的库。

请参见 restart_with_reloader()函数代码; 您的脚本使用 subprocess.call()运行 再来一次

如果你将 use_reloader设置为 False,你会看到这种行为消失,但是你也会失去重新加载的功能:

app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)

你也可以在使用 flask run命令时禁用重新加载程序:

FLASK_DEBUG=1 flask run --no-reload

如果您希望在重新加载子进程时检测,可以使用 werkzeug.serving.is_running_from_reloader功能:

from werkzeug.serving import is_running_from_reloader


if is_running_from_reloader():
print(f"################### Restarting @ {datetime.utcnow()} ###################")

但是,如果需要设置模块全局变量,那么应该在函数上使用 @app.before_first_request室内设计师,并让该函数设置这样的全局变量。每次重新加载后,当第一个请求出现时,它只会被调用一次:

@app.before_first_request
def before_first_request():
print(f"########### Restarted, first request @ {datetime.utcnow()} ############")

请务必考虑到,如果您在使用分叉或新子进程处理请求的全规模 WSGI 服务器中运行此命令,那么将为每个新子进程调用 before_first_request处理程序

我也遇到了同样的问题,我通过将 app.debug设置为 False来解决这个问题。将它设置为 True会导致我的 __name__ == "__main__"被调用两次。

如果使用现代的 flask run命令,则不使用 app.run的任何选项。要完全禁用重装机,请传递 --no-reload:

FLASK_DEBUG=1 flask run --no-reload

此外,__name__ == '__main__'永远不会为真,因为应用程序不是直接执行的。使用来自 马丁的回答的相同想法,除了没有 __main__块。

if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
# do something only once, before the reloader


if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
# do something each reload

我也有同样的问题。我通过修改 main 并在其中插入 use _ reloader = False 解决了这个问题。如果有人在这里寻找解决这个问题的方法,然后下面的代码将让你开始,但是,你将删除代码中的变化被自动检测的功能,并重新启动应用程序将不会工作。在代码中每次编辑之后,必须手动停止并重新启动应用程序。

if __name__ == '__main__':
app.run(debug=True, use_reloader=False)

Flask 应用程序自身运行两次的原因之一可能是 Heroku 上的 WEB_CONCURRENCY设置配置。要设置为一,可以在控制台中编写 heroku config:set WEB_CONCURRENCY=1

在 Flask 0.11中,建议使用 flask run而不是 python application.py运行应用程序。使用后者可能导致代码运行两次。

正如这里所说:

从烧瓶0.11开始,推荐烧瓶法。原因是由于重新加载机制的工作方式有一些奇怪的副作用(比如执行某些代码两次...)

我正在使用 plugin-python-dotenv 我会把这个放到我的配置文件里-. flaskenv:

FLASK _ RUN _ RELOAD = False

这样我就不用两次烧瓶了。