kramer65
kramer65

Reputation: 54013

Why does running the Flask dev server run itself twice?

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

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

Upvotes: 180

Views: 57216

Answers (9)

Luis Felix
Luis Felix

Reputation: 11

Four others running into similar issues, that are not running flask, I resolved my problem by adding the following parameter when running my server:

python manage.py runserver --noreload

Upvotes: 0

Jiwei Wu
Jiwei Wu

Reputation: 135

The gist of my fix was to share a tmp file among all processes, if the file does not exist, start initializing code, including set up a scheduler. All other suggestions I tried, they either lose functionality of child processes for scalability or auto reload in debugging Flask provided.

  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()

`

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1124558

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().

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

If you set use_reloader to False you'll see the behaviour go away, but then you also lose the reloading functionality:

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

You can disable the reloader when using the flask run command too:

FLASK_DEBUG=1 flask run --no-reload

You can use the werkzeug.serving.is_running_from_reloader function if you wanted to detect when you are in the reloading child process:

from werkzeug.serving import is_running_from_reloader

if is_running_from_reloader():
    print(f"################### Restarting @ {datetime.utcnow()} ###################")

However, if you need to set up module globals, then you should instead use the @app.before_first_request decorator on 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
def before_first_request():
    print(f"########### Restarted, first request @ {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_request handlers may be invoked for each new subprocess.

Upvotes: 248

Kanglin Wu
Kanglin Wu

Reputation: 31

I am using plugin - python-dotenv and i will put this on my config file - .flaskenv:

FLASK_RUN_RELOAD=False

and this will avoid flask run twice for me.

Upvotes: 2

L A
L A

Reputation: 37

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

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

Upvotes: 1

Carvell Wakeman
Carvell Wakeman

Reputation: 156

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

Upvotes: 11

salsa_man
salsa_man

Reputation: 107

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

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...)

Upvotes: 8

trojek
trojek

Reputation: 3228

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

Upvotes: 0

davidism
davidism

Reputation: 127390

If you are using the modern flask run command, none of the options to app.run are used. To disable the reloader completely, pass --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.

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

Upvotes: 21

Related Questions