为什么运行 Flask 开发服务器会自行运行两次?
- 2024-12-03 08:44:00
- admin 原创
- 174
问题描述:
我正在使用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 是在您调用 时为 Flask 提供开发服务器的库app.run()
。
查看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
处理程序。
解决方案 2:
如果您使用的是现代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
解决方案 3:
我遇到了同样的问题,我通过设置app.debug
为解决了它False
。将其设置True
为 导致我的__name__ == "__main__"
被调用两次。
解决方案 4:
从 Flask 0.11 开始,建议使用flask run
而不是来运行你的应用程序python application.py
。使用后者可能会导致你的代码运行两次。
如此处所述:
... 从 Flask 0.11 开始,建议使用 flask 方法。这样做的原因是由于重新加载机制的工作方式,会产生一些奇怪的副作用(例如执行某些代码两次...)
解决方案 5:
我正在使用插件 - python-dotenv 并且我会将它放在我的配置文件 - .flaskenv 上:
FLASK_RUN_RELOAD=False
这将避免我运行两次 Flask。
解决方案 6:
我遇到了同样的问题。我通过修改主程序并在其中插入 use_reloader=False 解决了这个问题。如果有人在这里寻找解决此问题的方法,那么下面的代码将帮助您入门,但是,您将删除自动检测代码更改的功能,并且重新启动应用程序将不起作用。每次编辑代码后,您都必须手动停止并重新启动应用程序。
if __name__ == '__main__':
app.run(debug=True, use_reloader=False)
解决方案 7:
Flask 应用程序自行运行两次的可能原因之一是WEB_CONCURRENCY
Heroku 上的设置配置。要设置一个,您可以在控制台中写入heroku config:set WEB_CONCURRENCY=1
解决方案 8:
我的修复要点是在所有进程之间共享一个 tmp 文件,如果该文件不存在,则开始初始化代码,包括设置调度程序。我尝试过的所有其他建议,要么为了可扩展性而失去子进程的功能,要么在提供的 Flask 调试中自动重新加载。
import os.path
from apscheduler.schedulers.background import BackgroundScheduler
app = Flask(__name__)
def set_lastrun():
f = open('/tmp/lastrun','w')
f.write(f'{datetime.now()}')
f.close()
def get_lastrun():
return os.path.isfile('/tmp/lastrun')
def start_job_scheduler():
scheduler = BackgroundScheduler()
scheduler.add_job(func=your_job, trigger="interval", seconds=300)
scheduler.start()
def app_init():
if not get_lastrun():
set_lastrun()
start_job_scheduler()
app_init()
`
解决方案 9:
另外四个遇到类似问题的人没有运行 flask,我通过在运行服务器时添加以下参数解决了我的问题:
python manage.py runserver --noreload