为什么运行Flask开发服务器会运行两次



我使用Flask开发网站,在开发过程中,我使用以下文件运行Flask:

#!/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 ###################

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

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处理程序

如果使用现代flask run命令,则不会使用app.run的任何选项。要完全禁用重新加载程序,请通过--no-reload:

FLASK_DEBUG=1 flask run --no-reload

此外,__name__ == '__main__'永远不会为真,因为应用程序不是直接执行的。使用与Martijn的答案相同的想法,除了没有__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

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

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

如前所述:

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

我正在使用插件-python dotenv我会把它放在我的配置文件中。flaskenv:

FLASK_RUN_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

最新更新