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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25504149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:19:31  来源:igfitidea点击:

Why does running the Flask dev server run itself twice?

pythonflask

提问by kramer65

I'm using Flaskfor developing a website and while in development I run flask using the following file:

我正在使用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')

When I start the server, or when it auto-restarts because files have been updated, it always shows the print line twice:

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

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

Although it is not really a problem (the rest works as expected), I simply wonder why it behaves like this? Any ideas?

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

采纳答案by Martijn Pieters

The Werkzeug reloader spawns a child process so that it can restart that process each time your code changes. Werkzeug is the library that supplies Flask with the development server when you call app.run().

Werkzeug 重新加载器会生成一个子进程,以便在每次代码更改时重新启动该进程。Werkzeug 是在您调用app.run().

See the restart_with_reloader()function code; your script is run againwith subprocess.call().

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

If you set use_reloaderto Falseyou'll see the behaviour go away, but then you also lose the reloading functionality:

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

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

You can disable the reloader when using the flask runcommand too:

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

FLASK_DEBUG=1 flask run --no-reload

You can look for the WERKZEUG_RUN_MAINenvironment variable if you wanted to detect when you are in the reloading child process:

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

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

However, if you need to set up module globals, then you should instead use the @app.before_first_requestdecoratoron a function and have that function set up such globals. It'll be called just once after every reload when the first request comes in:

但是,如果您需要设置模块全局变量,那么您应该改为在函数上使用@app.before_first_request装饰器并让该函数设置此类全局变量。当第一个请求进来时,它会在每次重新加载后调用一次:

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

Do take into account that if you run this in a full-scale WSGI server that uses forking or new subprocesses to handle requests, that before_first_requesthandlers maybe invoked for each new subprocess.

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

回答by Carvell Wakeman

I had the same issue, and I solved it by setting app.debugto False. Setting it to Truewas causing my __name__ == "__main__"to be called twice.

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

回答by davidism

If you are using the modern flask runcommand, none of the options to app.runare used. To disable the reloader completely, pass --no-reload:

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

FLASK_DEBUG=1 flask run --no-reload

Also, __name__ == '__main__'will never be true because the app isn't executed directly. Use the same ideas from Martijn's answer, except without the __main__block.

此外,__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

回答by L A

I had the same issue. I solved it by modifying my main and inserting use_reloader=False into it. If any body is here looking for a workaround for this problem then below code will get you started, however you will the functionality of changes in code being detected automatically by and restarting the application will not work. You will have to manually stop and restart you application after each edit in code.

我遇到过同样的问题。我通过修改我的 main 并将 use_reloader=False 插入其中来解决它。如果有人在这里寻找解决此问题的方法,那么下面的代码将使您入门,但是您将自动检测代码更改的功能并重新启动应用程序将不起作用。每次编辑代码后,您都必须手动停止并重新启动应用程序。

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

回答by trojek

One of the possible reason why the Flask app run itself twice is a configuration of WEB_CONCURRENCYsetting on Heroku. To set into one, you can write in console heroku config:set WEB_CONCURRENCY=1

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

回答by salsa_man

From Flask 0.11, it's recommended to run your app with flask runrather than python application.py. Using the latter could result in running your code twice.

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

As stated here:

如此处所述

... from Flask 0.11 onwards the flask method is recommended. The reason for this is that due to how the reload mechanism works there are some bizarre side-effects (like executing certain code twice...)

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

回答by pfabri

An observation regarding threads

关于线程的观察

This is particularly annoying when your application uses threads as they will be fired twice at startup. As far as I tried singletons don't remedy this either (which is surprising). However, adding an initial delay of a few seconds prior to your thread starts can solve the issue.

当您的应用程序使用线程时,这尤其令人讨厌,因为它们将在启动时被触发两次。就我尝试过的单身人士而言,也不能解决这个问题(这令人惊讶)。但是,在线程启动之前添加几秒钟的初始延迟可以解决问题。

If the app restarts quicker than before your delay period is over the given thread is only spawned once, after the restart.

如果应用程序的重启速度比延迟期结束之前更快,则给定线程仅在重启后生成一次。