Python/Flask: Difference between revisions

From Omnia
Jump to navigation Jump to search
(Created page with "== Flask == == Installation == ## Linux / macOS mkdir myproject cd myproject # python3 -m venv .flask python3 -m venv .venv . .venv/bin/activate ## Windows mkdir myproject cd myproject py -3 -m venv .venv .venv\Scripts\activate ## Next Common Step # pip install Flask pip3 install Flask # End deactivate References: * https://flask.palletsprojects.com/en/stable/installation/ == Quick Start == Hello World helloworld.py <pre> from flask import Flask...")
 
 
(11 intermediate revisions by the same user not shown)
Line 28: Line 28:
== Quick Start ==
== Quick Start ==


Hello World
=== Flask Hello World ===


helloworld.py
helloworld.py
Line 38: Line 38:
@app.route("/")
@app.route("/")
def hello_world():
def hello_world():
     return "<p>Hello, World!</p>"
     return "<p>Hello, World!</p>\n"
</pre>
</pre>


Line 44: Line 44:
Run the server:
Run the server:
  flask --app helloworld run
  flask --app helloworld run
NOTE: As a shortcut, if the file is named app.py or wsgi.py, you don’t have to use --app. See Command Line Interface for more details.
* Meaning, just simply rename helloworld.py to app.py (or wsgi.py) and you can simply run run:
flask run
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
Note:
* Running on http://127.0.0.1:5000
Test the server:
<pre>
curl http://127.0.0.1:5000
  <p>Hello, World!</p>
</pre>


References:
References:
* https://flask.palletsprojects.com/en/stable/quickstart/
* https://flask.palletsprojects.com/en/stable/quickstart/
=== Hello World Headers ===
<pre>
$ curl -i http://127.0.0.1:5000
HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.3
Date: Sat, 13 Dec 2025 22:05:42 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 20
Connection: close
<p>Hello, World!</p>
</pre>
== WSGI ==
=== Apache mod_wsgi-express ===
<pre>
$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install .  # install your application
$ pip install mod_wsgi
</pre>
wsgi.py :  (or yourapp.wsgi)
<pre>
## IIMPORT PATTERN
from hello import app
application = app
## OR
## FACTORY PATTERN
from hello import create_app
application = create_app()
</pre>
Configure mod_wsgi-express and specify the number of worker processes:
mod_wsgi-express start-server wsgi.py --processes 4
Example running mod_wsgi-express as root, to bind to port 80/443, but then drop permissions and binding app as different user:
sudo /home/hello/.venv/bin/mod_wsgi-express start-server /home/hello/wsgi.py \
    --user hello --group hello --port 80 --processes 4
Reference: https://flask.palletsprojects.com/en/stable/deploying/mod_wsgi/
=== Apache mod_wsgi and WSGIScriptAlias ===
Another WSGI option using mod_wsgi and WSGIScriptAlias
Install:
sudo apt install apache2 libapache2-mod-wsgi-py3
TIP: You can also use the touch command on your .wsgi file to gracefully restart the application processes without restarting the entire Apache server when you make code changes.
/path/to/your/yourapp.wsgi : ( the "bridge" between apache and Flask )
<pre>
import sys
import os
# Add your project directory to Python's path
project_home = os.path.dirname(os.path.abspath(__file__))
if project_home not in sys.path:
    sys.path.insert(0, project_home)
# Import the 'app' object from your Flask application file (e.g., app.py)
from app import app as application
</pre>
Virtual Host :
<pre>
<VirtualHost *:80>
    ServerName yourdomain.com
    # Points to your WSGI script
    WSGIScriptAlias / /path/to/your/yourapp.wsgi
    # Configure daemon processes
    WSGIDaemonProcess yourapp_daemon user=www-data group=www-data threads=5
    WSGIProcessGroup yourapp_daemon
    # Grant access to the application directory
    <Directory /path/to/your/project/folder>
        WSGIProcessGroup yourapp_daemon
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
        Require all granted
    </Directory>
    ErrorLog /var/log/apache2/yourdomain.com_error.log
    CustomLog /var/log/apache2/yourdomain.com_access.log combined
</VirtualHost>
</pre>
Enable the virtual host:
<pre>
# On Ubuntu/Debian
sudo a2ensite yourdomain.com.conf
sudo systemctl restart apache2
# On Fedora/RHEL
sudo systemctl restart httpd
</pre>
Prerequisites
* Python Virtual Environment: Your Flask application should be installed in a dedicated Python virtual environment for dependency isolation.
* Apache Web Server: Apache must be installed and running.
* mod_wsgi: The mod_wsgi package must be installed and enabled for the correct Python version (e.g., libapache2-mod-wsgi-py3 on Ubuntu systems).
* No app.run(): Ensure that any app.run() calls are removed or placed inside an if __name__ == '__main__': block in your Flask app's main file, as Apache will manage the server lifecycle.
=== Reverse Proxy ===
Tell Flask it is being reverse Proxied:
<pre>
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(
    app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
)
</pre>
reference: https://flask.palletsprojects.com/en/stable/deploying/proxy_fix/
Apapache Configuration:
<pre>
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPass / http://127.0.0.1:8000/
RequestHeader set X-Forwarded-Proto http
RequestHeader set X-Forwarded-Prefix /
</pre>
reference: https://flask.palletsprojects.com/en/stable/deploying/apache-httpd/
=== Systemd Flask Service ===
/etc/systemd/system/myproject.service
<pre>
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=youruser
WorkingDirectory=/path/to/your/project
Environment="FLASK_ENV=production"
ExecStart=/path/to/your/project/venv/bin/gunicorn -w 4 'app:app' -b 0.0.0.0:8000
Restart=always
[Install]
WantedBy=multi-user.target
</pre>
sudo systemctl daemon-reload
sudo systemctl start myproject
sudo systemctl enable myproject
Check logs with:
sudo systemctl status myproject
journalctl -u myproject
== keywords ==

Latest revision as of 22:42, 13 December 2025

Flask

Installation

## Linux / macOS
mkdir myproject
cd myproject
# python3 -m venv .flask
python3 -m venv .venv
. .venv/bin/activate
## Windows
mkdir myproject
cd myproject
py -3 -m venv .venv
.venv\Scripts\activate
## Next Common Step
# pip install Flask
pip3 install Flask
# End
deactivate

References:

Quick Start

Flask Hello World

helloworld.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>\n"


Run the server:

flask --app helloworld run

NOTE: As a shortcut, if the file is named app.py or wsgi.py, you don’t have to use --app. See Command Line Interface for more details.

  • Meaning, just simply rename helloworld.py to app.py (or wsgi.py) and you can simply run run:
flask run

WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

Note:

* Running on http://127.0.0.1:5000

Test the server:

curl http://127.0.0.1:5000
   <p>Hello, World!</p>

References:

Hello World Headers

$ curl -i http://127.0.0.1:5000
HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.3
Date: Sat, 13 Dec 2025 22:05:42 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 20
Connection: close

<p>Hello, World!</p>

WSGI

Apache mod_wsgi-express

$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install .  # install your application
$ pip install mod_wsgi

wsgi.py : (or yourapp.wsgi)

## IIMPORT PATTERN
from hello import app
application = app

## OR

## FACTORY PATTERN
from hello import create_app
application = create_app()

Configure mod_wsgi-express and specify the number of worker processes:

mod_wsgi-express start-server wsgi.py --processes 4

Example running mod_wsgi-express as root, to bind to port 80/443, but then drop permissions and binding app as different user:

sudo /home/hello/.venv/bin/mod_wsgi-express start-server /home/hello/wsgi.py \
   --user hello --group hello --port 80 --processes 4

Reference: https://flask.palletsprojects.com/en/stable/deploying/mod_wsgi/

Apache mod_wsgi and WSGIScriptAlias

Another WSGI option using mod_wsgi and WSGIScriptAlias

Install:

sudo apt install apache2 libapache2-mod-wsgi-py3

TIP: You can also use the touch command on your .wsgi file to gracefully restart the application processes without restarting the entire Apache server when you make code changes.


/path/to/your/yourapp.wsgi : ( the "bridge" between apache and Flask )

import sys
import os

# Add your project directory to Python's path
project_home = os.path.dirname(os.path.abspath(__file__))
if project_home not in sys.path:
    sys.path.insert(0, project_home)

# Import the 'app' object from your Flask application file (e.g., app.py)
from app import app as application


Virtual Host :

<VirtualHost *:80>
    ServerName yourdomain.com

    # Points to your WSGI script
    WSGIScriptAlias / /path/to/your/yourapp.wsgi

    # Configure daemon processes
    WSGIDaemonProcess yourapp_daemon user=www-data group=www-data threads=5
    WSGIProcessGroup yourapp_daemon

    # Grant access to the application directory
    <Directory /path/to/your/project/folder>
        WSGIProcessGroup yourapp_daemon
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
        Require all granted
    </Directory>

    ErrorLog /var/log/apache2/yourdomain.com_error.log
    CustomLog /var/log/apache2/yourdomain.com_access.log combined
</VirtualHost>


Enable the virtual host:

# On Ubuntu/Debian
sudo a2ensite yourdomain.com.conf
sudo systemctl restart apache2

# On Fedora/RHEL
sudo systemctl restart httpd


Prerequisites

  • Python Virtual Environment: Your Flask application should be installed in a dedicated Python virtual environment for dependency isolation.
  • Apache Web Server: Apache must be installed and running.
  • mod_wsgi: The mod_wsgi package must be installed and enabled for the correct Python version (e.g., libapache2-mod-wsgi-py3 on Ubuntu systems).
  • No app.run(): Ensure that any app.run() calls are removed or placed inside an if __name__ == '__main__': block in your Flask app's main file, as Apache will manage the server lifecycle.

Reverse Proxy

Tell Flask it is being reverse Proxied:

from werkzeug.middleware.proxy_fix import ProxyFix

app.wsgi_app = ProxyFix(
    app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
)

reference: https://flask.palletsprojects.com/en/stable/deploying/proxy_fix/

Apapache Configuration:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPass / http://127.0.0.1:8000/
RequestHeader set X-Forwarded-Proto http
RequestHeader set X-Forwarded-Prefix /

reference: https://flask.palletsprojects.com/en/stable/deploying/apache-httpd/

Systemd Flask Service

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=youruser
WorkingDirectory=/path/to/your/project
Environment="FLASK_ENV=production"
ExecStart=/path/to/your/project/venv/bin/gunicorn -w 4 'app:app' -b 0.0.0.0:8000
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start myproject
sudo systemctl enable myproject

Check logs with:

sudo systemctl status myproject
journalctl -u myproject

keywords