%%file app.py
from flask import Flask
# Create a flask
= Flask(__name__)
app
# Create an API end point
@app.route('/')
def say_hello():
return "Hello World"
if __name__ == '__main__':
app.run()
Production Environment with ML Model
Our task is to deploy a Python application implementing REST API tasks. Upon client request, the server will respond based on predictions generated from a certain model.
This image will be containerized using a Dockerfile
, making server deployment possible regardless of the platform.
We will accomplish our task using the Flask
library version 3.0.3.
There are other libraries that can accomplish this task.
Check at home if you can use them yourself, or at least read the code.
- FastAPI
- Seldon
- MLFlow
- Node.js - Express
Minimal Flask Application Code
We want to run our application locally and then easily transfer and execute it on any computer. Therefore, a natural solution is to save the code to a file with the .py
extension.
To automatically save the application code to the app.py
file, we will use the magic command %%file file.py
.
Note! In the Flask documentation, the last two lines starting the server are not present in the sample code. Furthermore, the command to start the server is
flask run
, notpython app.py
. Let’s explain what the sample code contains:
from flask import Flask
: Imports the Flask library.app = Flask(__name__):
Creates the API server interface.- Subpage code using a decorator: Here, a route of the application is defined. Using a decorator (e.g., @app.route(‘/’)), you specify which URL address should trigger the associated function. Typically, the function returns the content that the client will receive when accessing this path.
@app.route('/')
def say_hello():
return "Hello World"
To demonstrate how the decorator works, let’s define the following function:
def make_pretty(func):
def inner():
print("decorator working")
func()return inner()
def test():
print("abc")
make_pretty(test)
decorator working
abc
@make_pretty
def test2():
print("test2")
decorator working
test2
@make_pretty
def test3():
print("anything else")
decorator working
anything else
Python Environment
In order for the application code in app.py to run, we need a Python interpreter installed on our computer. However, simply having an interpreter is not sufficient for our application. To fully run it, we need to create an environment (preferably virtual) where all the necessary libraries (e.g., Flask) are available.
Note: All terminal commands will be for Linux/Mac OS versions.
which python
which python3
which pip
which pip3
All these commands should point to the folder with the default Python environment.
Generate and run a virtual environment locally by entering the following command in the terminal:
python3 -m venv .venv
source .venv/bin/activate
Good practice: a Python environment is nothing more than a directory. In our version, it’s a hidden directory named
.venv
. If you copy this directory elsewhere, it will cease to function as your Python environment. Therefore, recreating it does not involve copying it. If your project is associated with a version control system like GIT, make sure the environment directory is not added to the repository. You can achieve this by adding the appropriate entry to the.gitignore
file.
Having created a new environment, check which libraries are present in it.
pip list
Package Version
---------- -------
pip 23.2.1
pyspark 3.4.1
setuptools 65.5.0
We can check the Python and pip commands again
which python
which pip
By default, the libraries pip
and setuptools
should appear (pyspark comes from our internal image).
Install the Flask library:
pip install flask
pip list
Package Version
------------ -------
blinker 1.7.0
click 8.1.7
Flask 3.0.3
itsdangerous 2.1.2
Jinja2 3.1.3
MarkupSafe 2.1.5
pip 23.2.1
pyspark 3.4.1
setuptools 65.5.0
Werkzeug 3.0.2
As you can see, installing the Flask library also forced the installation of other packages.
The only way to transfer the Python environment is to install it on a new machine and manually install all the packages. However, to avoid installing each package individually, we can use a configuration file called requirements.txt
with a list of packages.
Remember - each package should include the version number. Otherwise, it may turn out that new package versions break compatibility with your code. To create the configuration file, use the following command in the terminal:
pip freeze >> requirements.txt
You can use the generated file on any machine to install and recreate the required Python runtime environment.
Side note: At the time of preparing the materials, Flask was in version 3.0.1 - today it is already available in version 3.0.3.
To install packages from the file, use the following command:
pip install -r requierements.txt
We now have two files: app.py
and requirements.txt
.
By moving them to any project on GitHub, we can run our application wherever a Python interpreter is available, allowing us to create a new virtual environment and install libraries from the requirements.txt file.
For full automation, it would be useful to be able to run the Python environment on any machine.
To achieve this, create a Dockerfile
:
%%file Dockerfile
3.11-slim-buster
FROM python:
/app
WORKDIR
COPY requirements.txt requirements.txt
-r requirements.txt
RUN pip install
COPY app.py .
=app
ENV FLASK_APP
8000
EXPOSE "flask", "run", "--host", "0.0.0.0", "--port", "8000"] CMD [
The above file allows Docker Desktop to run an image utilizing a basic operating system (here Linux) along with a basic Python 3.11 environment.
Furthermore, this file copies necessary files (app.py, requirements.txt) into the Docker image.
The RUN
command allows executing any bash command inside the Docker image.
The CMD
command allows running a command to start the server in a mode that won’t close this command.
The last piece of information is setting the port to 8000.
# creating docker container from Dockerfile
docker build -t modelML .
# run container
docker run -p 8000:8000 modelML
Running the Server Locally
The server can be started in at least two ways.
Starting the Server via Terminal
python app.py
or (if there is no app.run() code starting the server).
flask run
You should see information similar to the following
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
Running the Server via Notebook
Directly running the code in a notebook will start the server and halt any further code execution. To avoid this, you can use the subprocess
library.
import subporcess
= subprocess.Popen(["python", "app.py"]) p
If we need to close the subprocess, execute
p.kill()
With the server running, you can query it using:
curl localhost:5000
or in jupyter notebook:
import requests
= requests.get("http://127.0.0.1:5000/")
response
print(response.content) # Hello World
print(response.status_code) # 200