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

kra*_*r65 81 python 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')
Run Code Online (Sandbox Code Playgroud)

当我启动服务器时,或者由于文件已更新而自动重启时,它始终显示两次打印行:

################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ers 121

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

查看restart_with_reloader()功能代码 ; 你的脚本运行再次subprocess.call().

如果你设置use_reloaderFalse你会看到行为消失,但你也失去了重新加载功能:

app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)
Run Code Online (Sandbox Code Playgroud)

您也可以在使用flask run命令时禁用重新加载器:

FLASK_DEBUG=1 flask run --no-reload
Run Code Online (Sandbox Code Playgroud)

WERKZEUG_RUN_MAIN如果要检测何时处于重新加载子进程中,可以查找环境变量:

import os
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
    print '################### Restarting @ {} ###################'.format(
        datetime.utcnow())
Run Code Online (Sandbox Code Playgroud)

但是,如果你需要设置模块全局变量,那么你应该在函数上使用@app.before_first_request装饰器并让该函数设置这样的全局变量.当第一个请求进入时,每次重新加载后都会调用一次:

@app.before_first_request
def before_first_request():
    print '########### Restarted, first request @ {} ############'.format(
        datetime.utcnow())
Run Code Online (Sandbox Code Playgroud)

请注意,如果在使用分叉或新子进程处理请求的全尺寸WSGI服务器中运行此服务器,则可以为每个新子进程调用该before_first_request处理程序.

  • 喔好吧。感谢您的解释!那么它被认为是正常的行为吗?至少好,我的代码没什么问题.. :) (2认同)

dav*_*ism 9

如果您使用的是现代flask run命令,则不使用任何选项app.run.要完全禁用重新加载器,请传递--no-reload:

FLASK_DEBUG=1 flask run --no-reload
Run Code Online (Sandbox Code Playgroud)

此外,__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
Run Code Online (Sandbox Code Playgroud)


小智 7

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

正如这里所述

...从 Flask 0.11 开始,建议使用 Flask 方法。这样做的原因是,由于重新加载机制的工作方式,存在一些奇怪的副作用(例如执行某些代码两次......)


小智 6

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

(我会发布这个作为评论,但我没有足够的代表.作为答案发布,希望它能帮助别人)