Rking14
Rking14

Reputation: 345

Python REST API not working properly in Docker container

I created a simple ML API using python with flask. It gets data from sample.csv and trains a logistic regression model based on that. I also have a '/predict' endpoint where I can input parameters in for the model to predict.

Example localhost:80/predict?weight1=1.2&weight2=0.00123&&weight3=0.45 will output { "predicted": 1}

main.py:

from sklearn.linear_model import LogisticRegression
from flask import Flask, request
import numpy as np

# Create Flask object to run
app = Flask(__name__)

@app.route('/')
def home():
    return "Predicting status from other features"


@app.route('/predict')
def predict():
    # Get values from the server
    weight1 = request.args['weight1']
    weight2 = request.args['weight2']
    weight3 = request.args['weight3']

    testData = np.array([weight1, weight2, weight3]).reshape(1, -1)

    class_predicted = logisticRegr.predict(testData.astype(float))

    output = "{ \"predicted\": " + "\"" + class_predicted[0] + "\"" +  "}"

    return output


# Train and load the model based on the MetroPCS_Sample
def load_model():
    global logisticRegr
    label_y = []
    label_x = []

    with open('sample.csv') as f:
        lines = f.readlines()
        for line in lines[1:]:
            # Adding labels to label_y
            label_y.append(int(line[0]))
            line = line.strip().split(",")
            x_data = []
            for e in line[1:]:
            # Adding other features to label_x
                x_data.append(float(e))
            label_x.append(x_data)


    train_x = label_x[:700]
    train_y = label_y[:700]

    test_x = label_x[700:1000]
    test_y = label_y[700:1000]

    logisticRegr = LogisticRegression()


    logisticRegr.fit(train_x, train_y)

    predictions = logisticRegr.predict(test_x)

    score = logisticRegr.score(test_x, test_y)
    # print score

if __name__ == "__main__":
    print("Starting Server...")

    # Call function that loads Model
    load_model()

    # Run Server
    app.run(host="127.0.0.1", debug=True, port=80) 

Everything works well when I run this script without a container.

However, when I placed it in a container and run it, I get the following error:

NameError: global name 'logisticRegr' is not not defined

Dockerfile

FROM tiangolo/uwsgi-nginx-flask:python2.7

# copy over our requirements.txt file
COPY requirements.txt /tmp/

# upgrade pip and install required python packages
RUN pip install -U pip
RUN pip install -r /tmp/requirements.txt

COPY ./app /app

ENV MESSAGE "hello"

requirements.txt

Flask
numpy
sklearn
scipy

Do you know what can cause the NameError when the script is inside a container?

Upvotes: 1

Views: 843

Answers (1)

Asav Patel
Asav Patel

Reputation: 1162

in your def load_model(). you have global logisticRegr. just using global keyword doesn't make your variable global.

global is used when you want to access and change global variable inside your function. since your logisticRegr is not global,

when you are trying to access it in def predict(),

class_predicted = logisticRegr.predict(testData.astype(float)) you would get NameError: global name 'logisticRegr' is not defined.

now to solve your issue. initialize/declare your logisticRegr model variable after you initialize your app variable like this:

# Create Flask object to run
app = Flask(__name__)
logisticRegr = LogisticRegression()

and then remove variable initialization from your load_model after test_y = label_y[700:1000]

PS : It's recommended to capitalize your global variables. to easily recognize them in your code.

Upvotes: 1

Related Questions