REST API with Flask

Client-Serwer

The Flask library handles adding subpages and communication with the server using functions wrapped with a decorator. Example of a decorator:

  1. We define a function that takes another function as a parameter.
  2. We define an inner function (everything in Python is an object) that executes the passed function and displays information about its execution.

Python Decorator code

# CODE
import subprocess
import requests
%%file app1.py

from flask import Flask

# Create a flask
app = Flask(__name__)

# Create an API end point
@app.route('/hello')
def say_hello():
    return "Hello World"

@app.route('/')
def say_he():
    return "Hello from main site"

if __name__ == '__main__':
    app.run()
p = subprocess.Popen(["python", "app1.py"])
adres_url = "http://127.0.0.1:5000/hello"
response = requests.get(adres_url)
# take content field from response object
# YOUR CODE
# take bad adress

adres_url = " "

response = requests.get(adres_url)

# Check if status_code field is 200
# YOUR CODE

run kill() method for p object

# YOUR CODE

Check any request and raspone whe your serwer is down

# YOUR CODE
response = ...

URL Adress with GET method for a sanding data

%%file app2.py

from flask import Flask
from flask import request

# Create a flask
app = Flask(__name__)

# Create an API end point
@app.route('/hello', methods=['GET'])
def say_hello():
    name = request.args.get("name", "") # tutaj leci str
    title = request.args.get("title", "")
    if name:
        resp = f"Hello {title} {name}" if title else f"Hello {name}"
    else:
        resp = f"Hello {title}" if title else "Hello"
    return resp

if __name__ == '__main__':
    app.run(port=5005)
p = subprocess.Popen(["python", "app2.py"])
response = requests.get("http://127.0.0.1:5005/hello")
response.content

add variables for url adress ?name=....

response = requests.get("http://127.0.0.1:5005/hello?name=Sebastian")
response.content

Try json answear

from flask import jsonify

def moja_f():
    ...
    return jsonify(reponse=resp)

An interesting and more functional solution for ML models is the [litServe](https://lightning.ai/litserve) library.

Notice the pipeline, which is written in a functional style.

::: {#389512cc-55fe-43e6-b0d5-a627e60399a7 .cell execution_count=4}
``` {.python .cell-code}
%%file app_lit.py
import litserve as ls

class SimpleLitAPI(ls.LitAPI):
    def setup(self, device):
        self.model1 = lambda x: x**2
        self.model2 = lambda x: x**3

    def decode_request(self, request):
        return request["input"]

    def predict(self, x):
        squared = self.model1(x)
        cubed = self.model2(x)
        output = squared + cubed
        return {"output": output}

    def encode_response(self, output):
        return {"output": output}

if __name__ == "__main__":
    api = SimpleLitAPI()
    server = ls.LitServer(api)
    server.run(port=5001)
Overwriting app_lit.py

:::

import subprocess

p = subprocess.Popen(["python", "app_lit.py"])
import requests

response = requests.post("http://127.0.0.1:5001/predict", json={"input": 4.0})
print(f"Status: {response.status_code}\nResponse:\n {response.text}")
Status: 200
Response:
 {"output":{"output":80.0}}
p.kill()

Docker container

Plik aplikacji app.py

%%file app.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "<h1>hello world</h1>"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

plik requirements.txt w którym zamieścimy potrzebne biblioteki

%%file requirements.txt
Flask==3.0.1

Dockerfile

  • pobranie obrazu systemu z pythonem
  • kopia pliku z wymaganymi bibliotekami
  • instalacja wymaganych bibliotek w środowisku
  • skopiowanie pliku aplikacji
  • uruchomienie aplikacji
%%file Dockerfile
FROM python:3.11-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

COPY app.py .

ENV FLASK_APP=app

EXPOSE 5000
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "5000"]
docker build -t test_hello .

docker run -p 5000:5000 test_hello