为啥运行 Flask 开发服务器会自行运行两次?
Posted
技术标签:
【中文标题】为啥运行 Flask 开发服务器会自行运行两次?【英文标题】:Why does running the Flask dev server run itself twice?为什么运行 Flask 开发服务器会自行运行两次? 【发布时间】:2014-10-19 16:19:28 【问题描述】:我使用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 ###################
虽然这不是一个真正的问题(其余的按预期工作),但我只是想知道它为什么会这样?有什么想法吗?
【问题讨论】:
【参考方案1】:Werkzeug 重新加载器会生成一个子进程,以便在每次代码更改时重新启动该进程。 Werkzeug 是当您调用 app.run()
时为 Flask 提供开发服务器的库。
见restart_with_reloader()
function code;您的脚本再次运行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
function:
from werkzeug.serving import is_running_from_reloader
if is_running_from_reloader():
print(f"################### Restarting @ datetime.utcnow() ###################")
但是,如果您需要设置模块全局变量,那么您应该在函数上使用 @app.before_first_request
decorator 并让该函数设置此类全局变量。当第一个请求进来时,它会在每次重新加载后被调用一次:
@app.before_first_request
def before_first_request():
print(f"########### Restarted, first request @ datetime.utcnow() ############")
请注意,如果您在使用分叉或新子进程来处理请求的完整 WSGI 服务器中运行此程序,则可能会为每个新子进程调用 before_first_request
处理程序。
【讨论】:
【参考方案2】:我遇到了同样的问题,我通过将app.debug
设置为False
解决了这个问题。将其设置为 True
会导致我的 __name__ == "__main__"
被调用两次。
【讨论】:
我的__main__
仍然运行两次app.debug = False
和app.run_server(debug=False)
。你确定这是为你做的,还是你可以发布一些可重现的代码来试试?
更改 app.debug 是我为自己解决问题所做的一切。你能确认烧瓶服务器启动时 main 只运行了两次吗?尝试运行一个最小的工作示例,看看是否出现问题。还可以尝试运行一个在多个 python 版本中失败的最小示例,这可能是一个问题。我已经将我的项目迁移到 Java 和 SparkJava 而不是 python 和烧瓶,所以我不记得究竟是什么解决了这个问题。
我通过plotly dash
使用flask
,发现他们最近将changed the default debug
参数传递给flask
。我猜我在上面弄错了,可能是app.debug=False
(它可能被默认参数覆盖为run_server
),或者只是在不传递True
的情况下尝试过,没有如上所示明确设置。这对我来说现在可以正常工作(确保debug=False
)。谢谢!【参考方案3】:
如果您使用现代的flask run
命令,则不会使用app.run
的任何选项。要完全禁用重新加载器,请传递 --no-reload
:
FLASK_DEBUG=1 flask run --no-reload
另外,__name__ == '__main__'
永远不会是真的,因为应用程序不是直接执行的。使用与 Martijn's answer 相同的想法,但没有 __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
【讨论】:
【参考方案4】:我遇到了同样的问题。我通过修改我的 main 并将 use_reloader=False 插入其中来解决它。如果有人在这里寻找解决此问题的方法,那么下面的代码将帮助您入门,但是,您将删除自动检测代码更改的功能,并且重新启动应用程序将不起作用。每次编辑代码后,您都必须手动停止并重新启动应用程序。
if __name__ == '__main__':
app.run(debug=True, use_reloader=False)
【讨论】:
【参考方案5】:Flask 应用程序运行两次的可能原因之一是 Heroku 上的 WEB_CONCURRENCY
设置配置。要设置为一个,您可以在控制台中编写
heroku config:set WEB_CONCURRENCY=1
【讨论】:
【参考方案6】:从 Flask 0.11 开始,建议使用 flask run
而不是 python application.py
运行您的应用程序。使用后者可能会导致您的代码运行两次。
As stated here:
...从 Flask 0.11 开始,推荐使用烧瓶方法。原因是由于重新加载机制的工作原理,存在一些奇怪的副作用(比如执行某些代码两次......)
【讨论】:
【参考方案7】:我正在使用插件 - python-dotenv 我会把它放在我的配置文件中 - .flaskenv:
FLASK_RUN_RELOAD=False
这将避免烧瓶为我运行两次。
【讨论】:
以上是关于为啥运行 Flask 开发服务器会自行运行两次?的主要内容,如果未能解决你的问题,请参考以下文章