Auto Reloading Python Flask App Upon Code Changes

Auto reloading python Flask app upon code changes

Run the flask run CLI command with debug mode enabled, which will automatically enable the reloader. As of Flask 2.2, you can pass --app and --debug options on the command line.

$ flask --app main.py --debug run

--app can also be set to module:app or module:create_app instead of module.py. See the docs for a full explanation.

More options are available with:

$ flask run --help

Prior to Flask 2.2, you needed to set the FLASK_APP and FLASK_ENV=development environment variables.

$ export FLASK_APP=main.py
$ export FLASK_ENV=development
$ flask run

It is still possible to set FLASK_APP and FLASK_DEBUG=1 in Flask 2.2.

Auto reloading Flask app when source code changes

The issue here, as stated in other answers, is that it looks like you moved from python run.py to foreman start, or you changed your Procfile from

# Procfile
web: python run.py

to

# Procfile
web: gunicorn --log-level=DEBUG run:app

When you run foreman start, it simply runs the commands that you've specified in the Procfile. (I'm going to guess you're working with Heroku, but even if not, this is nice because it will mimic what's going to run on your server/Heroku dyno/whatever.)

So now, when you run gunicorn --log-level=DEBUG run:app (via foreman start) you are now running your application with gunicorn rather than the built in webserver that comes with Flask. The run:app argument tells gunicorn to look in run.py for a Flask instance named app, import it, and run it. This is where it get's fun: since the run.py is being imported, __name__ == '__main__' is False (see more on that here), and so app.run(debug = True, port = 5000) is never called.

This is what you want (at least in a setting that's available publicly) because the webserver that's built into Flask that's used when app.run() is called has some pretty serious security vulnerabilities. The --log-level=DEBUG may also be a bit deceiving since it uses the word "DEBUG" but it's only telling gunicorn which logging statements to print and which to ignore (check out the Python docs on logging.)

The solution is to run python run.py when running the app locally and working/debugging on it, and only run foreman start when you want to mimic a production environment. Also, since gunicorn only needs to import the app object, you could remove some ambiguity and change your Procfile to

# Procfile
web: gunicorn --log-level=DEBUG app:app

You could also look into Flask Script which has a built in command python manage.py runserver that runs the built in Flask webserver in debug mode.

Is there a way to reload a flask app without code or file changes?

If you are running your application as a service (for example via systemctl), just call one of the many functions available in python to execute a command.

For example:

import os

@app.route('/reloadFlask', methods = ['POST'])
def reloadFlask():
os.system("systemctl restart <your_service_name>")

or:

import subprocess

@app.route('/reloadFlask', methods = ['POST'])
def reloadFlask():
p = subprocess.Popen(["systemctl", "restart", "<your_service_name>"], stdout=subprocess.PIPE)
out, err = p.communicate()

How to automate browser refresh when developing an Flask app with Python?

This is an interesting question you've raised so I built a quick and dirty Flask application which utilizes the livereload library. Listed below are the key steps for getting this to work:

  1. Download and install the livereload library:

    pip install livereload

  2. Within your main file which starts up your flask application, run.py in my particular case, wrap the flask application with the Server class provided by livereload.

For example, my run.py file looks like the following:

from app import app
from livereload import Server

if __name__ == '__main__':
server = Server(app.wsgi_app)
server.serve()

  1. Start your server again:

    python run.py

  2. Navigate to localhost in the browser and your code changes will be auto-refreshed. For me I took the default port of 5500 provided by livereload so my url looks like the following: http://localhost:5500/.

With those steps you should now be able to take advantage of auto-reloads for your python development, similar to what webpack provides for most frontend frameworks.

For completeness the codebase can be found here

Hopefully that helps!

Reload Flask app when template file changes

In my experience, templates don't even need the application to restart to be refreshed, as they should be loaded from disk everytime render_template() is called. Maybe your templates are used differently though.

To reload your application when the templates change (or any other file), you can pass the extra_files argument to Flask().run(), a collection of filenames to watch: any change on those files will trigger the reloader.

Example:

from os import path, walk

extra_dirs = ['directory/to/watch',]
extra_files = extra_dirs[:]
for extra_dir in extra_dirs:
for dirname, dirs, files in walk(extra_dir):
for filename in files:
filename = path.join(dirname, filename)
if path.isfile(filename):
extra_files.append(filename)
app.run(extra_files=extra_files)

See here: http://werkzeug.pocoo.org/docs/0.10/serving/?highlight=run_simple#werkzeug.serving.run_simple



Related Topics



Leave a reply



Submit