%%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__':
# domyślnie ustawia localhost i port 5000 app.run()
Środowisko produkcyjne z modelem ML
Naszym zadaniem jest wystawić aplikację w pythonie realizującą zadania REST API. Na ządanie klienta serwer udzieli odpowiedzi na podstawie predykcji wygenerowanej z jakiegoś modelu.
Obraz ten zostanie skonteryzowany z wykorzystaniem pliku Dockerfile
dzięki czemu uruchomienie serwera stanie się mozliwe nie zaleznie od platformy.
Nasze zadanie zrealizujemy z wykorzystaniem biblioteki Flask
w wersji 3.0.3
.
Istnieją inne biblioteki realizujące to zadanie. > Sprawdź samodzielnie w domu czy potrafisz je uzyć, albo przynajmniej przeczytać kod.
- FastAPI
- Seldon
- MLFlow
- Node js - Express
Kod minimalnej aplikacji flask
Naszą aplikację chcemy uruchomić lokalnie a potem w łatwy sposób przenieść i wykonać na dowolnym komputerze. Z tej przyczyny naturalnym rozwiązaniem jest zapis kodu do pliku z rozszerzeniem .py
.
W celu autozapisu kodu aplikacji do pliku app.py
wykorzystamy magiczną komendę %%file plik.py
.
Uwaga! w dokumentacji Flask w kodzie podstawowej aplikacji nie występują ostatnie dwie liniki uruchamiające serwer.
if __name__ == '__main__':
app.run()
Ponadto poleceniem uruchamiającym serwer jest flask run
a nie python app.py
.
Wyjaśnijmy co zawiera przykładowy kod.
from flask import Flask
Załadowanie bibliotekiapp = Flask(__name__)
utworzenie interfejsu serwera API- kod podstrony z wykorzystaniem dekoratora
@app.route('/')
def say_hello():
return "Hello World"
W celu pokazania jak działa dekorator zdefiniujmy następującą funkcję:
def make_pretty(func):
def inner():
print("decorator działa")
func()return inner()
Następnie funkcja testowa
def test():
print("abc")
make_pretty(test)
decorator działa
abc
Ale mozna rowniez inaczej
@make_pretty
def test2():
print("test2")
decorator działa
test2
@make_pretty
def test3():
print("jeszcze cos")
decorator działa
jeszcze cos
Środowisko Python
Aby kod aplikacji app.py mógł zostać uruchomiony potrzebujemy aby na naszym komputerze istniał jakiś interpreter języka Python. Samo posiadanie interpretatora nie jest jeszcze wystarczające dla naszej aplikacji. Do pełnego uruchomienia potrzebujemy wygenerować środowisko (najlepiej wirtualne) w który dostępne będą wszystkie potrzebne biblioteki (np. flask).
uwaga: wszystkie polecenia terminala dotyczyć będą wersji linux/mac os.
W pierwszej kolejności sprawdź czy dostępne są polecenia pozwalające realizować kod pythonowy.
which python
which python3
which pip
which pip3
Wszystkie te polecenia powinny wskazyać na folder z domyślnym środowiskiem Pythona.
Wygeneruj i uruchom środowisko wirtualne lokalnie wpisując w terminalu:
python3 -m venv .venv
source .venv/bin/activate
Dobra praktyka: środowisko python to nic innego jak katalog. W naszej wersji to katalog ukryty o nazwie
.venv
. Jeśli skopiujesz ten katalog gdzie indziej przestanie pełnić on swoją funkcję środowiska python. Dlatego jego odtworzenie nie polega na jego kopiowaniu. Jeśli Twój projekt jest powiązany ze środowiskiem kontroli wersji GIT zadbaj aby katalog środowiska nie był dodawany do repozytorium. Mozesz wykonać to działanie dodając odpowiedni wpis do pliki.gitignore
Posiadając utworzone nowe środowisko sprawdź jakie biblioteki się w nim znajdują.
pip list
Package Version
---------- -------
pip 23.2.1
pyspark 3.4.1
setuptools 65.5.0
Mozemy ponownie sprawdzić polecenia python i pip
which python
which pip
Domyślnie powinny pojawić się biblioteki pip
oraz setuptools
(pyspark pochodzi z naszego wewnętrzengo obrazu).
Doinstaluj bibliotekę flask
pip install flask==3.0.3
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
Jak widać instalacja biblioteki flask
wymusiła doinstalowanie równiez innych pakietów.
Jedyną mozliwością przeniesienia środowiska python jest jego ponowna instalacja na nowej maszynie i instalacja wszystkich pakietów. Aby jednak nie instalować kazdego pakietu osobno mozemy wykorzystać plik konfiguracyjny requirements.txt
zawierający listę pakietów.
Pamiętaj - kazdy pakiet powinien zawierać nr wersji pakietu. W innym przypadku moze okazać się, ze nowe werjse pakietów spowodują brak obsługi twojego kodu.
Aby utworzyć plik konfiguracyjny uzyj polecenia w terminalu:
pip freeze >> requirements.txt
Tak wygenerowany plik mozesz uzywać na dowolnej maszynie do instalacji i odtworzenia potrzebnego środowiska wykonawczego python.
Dygresja. W momencie przygotowywania materiałów Flask był w wersji 3.0.1 - dziś juz realizowany jest w wersji 3.0.3. Zmiany następują szybciej niz się wydaje.
Instalacja pakietów z pliku odbywa się z wykorzystaniem polecenia:
pip install -r requierements.txt
Mamy teraz dwa pliki: app.py
, i requirements.txt
. Przenosząc je do dowolnego projektu na serwerach github jesteśmy w stanie uruchomić naszą aplikację wszędzie tam gdzie dostępny będzie interpreter python na którym mozemy utworzyć nowe wirtualne środowisko i zainstalować biblioteki z pliku requirements.txt.
Do pełnej automatyzacji przydałaby się jeszcze mozliwość uruchomienia środowiska python na dowolnej maszynie.
W tym celu utwórz plik Dockerfile
:
%%file Dockerfile
3.11-slim-buster as builder
FROM python:
/app
WORKDIR
COPY requirements.txt .-r requirements.txt
RUN pip install
# Użyj innego obrazu dla obrazu końcowego
.11-slim-buster
FROM python3/app
WORKDIR # Skopiuj zależności z obrazu budującego
--from=builder /app /app
COPY
COPY app.py .
=app
ENV FLASK_APP
8000
EXPOSE "flask", "run", "--host", "0.0.0.0", "--port", "8000"] CMD [
Powyzszy plik pozwala w docker desktop uruchomić obraz wykorzystujący podstawowy system operacyjny (tutaj linux) wraz z podstawowym środowiskiem python3.11.
Ponadto plik ten kopiuje potrzebne pliki (app.py, requirements.txt) na obraz dockera.
Polecenie RUN
pozwala uruchomić dowolne polecenie bash wewnątrz obrazu dockera.
Polecenie CMD
pozwala uruchomić polecenie uruchamiające serwer w trybie tak by nie zamknąć tego polecenia.
Ostatnią informacją jest ustalenie portu na 8000.
# utworzenie kontenera na podstawie pliku Dockerfile
docker build -t modelML .
# uruchomienie kontenera
docker run -p 8000:8000 modelML
Uruchomienie serwera lokalnie
Uruchomienie serwera moze odbyć się na przynajmniej na dwa sposoby.
Uruchomienie serwera przez terminal
python app.py
lub (jeśli nie ma kodu app.run()
uruchamiającego serwer.)
flask run
Powinna pojawić się informacja podobna do ponizszej:
* 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
Uruchomienie serwera przez notatnik
Bezpośrenie uruchomienia kodu w notatniku spowoduje uruchomienie serwera i zatrzymanie jakiejkolwiek mozliwości realizacji kodu. Aby tego uniknąć mozesz wykorzystać bibliotekę subprocess
.
import subporcess
= subprocess.Popen(["python", "app.py"]) p
Jeśli potrzebujemy zamknąć subprocess wykonaj:
p.kill()
Posiadając uruchomiony serwer mozesz odpytac serwer wykorzystując:
curl localhost:5000
albo kod w notatniku:
import requests
= requests.get("http://127.0.0.1:5000/")
response
print(response.content) # Hello World
print(response.status_code) # 200