flask
python
auto-reload
web-development
code-changes

Auto reloading python Flask app upon code changes

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Flask provides built-in auto-reloading that restarts the development server whenever you modify Python source files. Enable it by running Flask in debug mode: set FLASK_DEBUG=1, pass debug=True to app.run(), or use the flask run --debug CLI command. Flask uses the Werkzeug reloader, which watches for file changes and automatically restarts the process. For non-Python files (templates, static assets), you may need additional configuration. Auto-reloading should only be used in development — never enable debug mode in production.

Method 1: app.run(debug=True)

python
1from flask import Flask
2
3app = Flask(__name__)
4
5@app.route('/')
6def hello():
7    return 'Hello, World!'
8
9if __name__ == '__main__':
10    app.run(debug=True)  # Enables auto-reload + debugger
bash
1python app.py
2# * Running on http://127.0.0.1:5000
3# * Restarting with stat
4# * Debugger is active!

debug=True enables both the auto-reloader and the interactive debugger. When you save a .py file, the server restarts automatically within a second.

bash
1# Set the app entry point
2export FLASK_APP=app.py
3
4# Run with debug mode
5flask run --debug
6
7# Or with reload explicitly
8flask run --reload
9
10# Or set via environment variable
11export FLASK_DEBUG=1
12flask run

The flask run CLI is the recommended way to start Flask applications. --debug enables both auto-reload and the debugger. --reload enables only the auto-reloader without the debugger.

Method 3: Environment Variables

bash
1# .env file (used with python-dotenv)
2FLASK_APP=app.py
3FLASK_DEBUG=1
4FLASK_RUN_PORT=5000
5FLASK_RUN_HOST=0.0.0.0
python
1# app.py — Flask automatically loads .env if python-dotenv is installed
2from flask import Flask
3
4app = Flask(__name__)
5
6@app.route('/')
7def index():
8    return 'Auto-reload enabled!'
bash
pip install python-dotenv
flask run
# Automatically reads .env and enables debug mode

Using .env files keeps debug configuration out of your source code. Flask loads .env automatically when python-dotenv is installed.

Choosing the Reloader Type

python
1if __name__ == '__main__':
2    # 'stat' reloader — polls files for changes (default)
3    app.run(debug=True, use_reloader=True)
4
5    # 'watchdog' reloader — uses OS file system events (faster)
6    # Requires: pip install watchdog
7    app.run(debug=True, use_reloader=True)
bash
1# Install watchdog for faster file change detection
2pip install watchdog
3
4# Flask automatically uses watchdog if installed
5flask run --debug
6# * Restarting with watchdog (inotify)

The default stat reloader polls files every second, which can be slow on large projects. The watchdog reloader uses OS-level file system events (inotify on Linux, FSEvents on macOS) for near-instant detection.

Watching Extra Files and Directories

bash
1# Watch additional file types beyond .py
2flask run --debug --extra-files templates/base.html:config.yaml
3
4# Watch entire directories
5flask run --debug --extra-files "templates/:static/css/"
python
1if __name__ == '__main__':
2    # Watch extra files programmatically
3    app.run(
4        debug=True,
5        extra_files=[
6            'config.yaml',
7            'templates/base.html',
8        ]
9    )

By default, Flask only watches .py files. Template changes (Jinja2) are picked up without a restart because templates are re-rendered on each request. But configuration files and other non-Python files need extra_files.

Docker Development Setup

yaml
1# docker-compose.yml
2version: '3.8'
3services:
4  web:
5    build: .
6    ports:
7      - "5000:5000"
8    volumes:
9      - .:/app          # Mount source code for live changes
10    environment:
11      - FLASK_APP=app.py
12      - FLASK_DEBUG=1
13    command: flask run --host=0.0.0.0 --debug
dockerfile
1# Dockerfile
2FROM python:3.11-slim
3WORKDIR /app
4COPY requirements.txt .
5RUN pip install -r requirements.txt
6COPY . .
7CMD ["flask", "run", "--host=0.0.0.0"]

Volume mounting (- .:/app) maps your local source code into the container. When you edit files locally, the Flask reloader inside the container detects the changes and restarts.

Disabling Auto-Reload

python
# Debug mode ON but reloader OFF
if __name__ == '__main__':
    app.run(debug=True, use_reloader=False)
bash
# CLI equivalent
flask run --debug --no-reload

Disable the reloader when debugging issues where the restart itself causes problems (e.g., database connections being dropped, or when attaching an external debugger like PyCharm or VS Code).

Common Pitfalls

  • Enabling debug mode in production: debug=True exposes the Werkzeug interactive debugger, which allows arbitrary Python code execution in the browser. Never deploy with debug mode enabled — it is a critical security vulnerability. Use environment variables to ensure debug mode is only active in development.
  • Auto-reload not detecting changes in non-.py files: Flask's reloader only watches Python files by default. Changes to templates are re-rendered per request (no restart needed), but changes to .yaml, .json, or other config files require --extra-files or extra_files= to be detected.
  • Infinite restart loop: If a syntax error occurs during import, the reloader may fail to restart cleanly. Fix the syntax error and the reloader will recover. If it does not, manually stop and restart the server.
  • Port already in use after crash: If the server crashes without cleaning up, the port (5000) may remain bound. Run lsof -i :5000 (macOS/Linux) or netstat -ano | findstr :5000 (Windows) to find and kill the orphaned process.
  • Reloader running code twice on startup: The Werkzeug reloader spawns a child process, so top-level code outside if __name__ == '__main__' executes twice. Put initialization code (database setup, scheduler start) inside the __name__ guard or use Flask's before_first_request (deprecated in 2.3+) or app factory pattern.

Summary

  • Use flask run --debug or app.run(debug=True) to enable auto-reloading during development
  • Install watchdog for faster file change detection via OS-level events
  • Use --extra-files to watch non-Python files like config files
  • Never enable debug mode in production — it exposes a remote code execution vulnerability
  • In Docker, mount source code as a volume for live reloading inside containers
  • The reloader spawns a child process, so top-level code runs twice — use if __name__ == '__main__' guards

Course illustration
Course illustration

All Rights Reserved.