I am brand new to python as of about 3 days ago and I need to build a prototype python server for an iOS work project. I followed a tutorial for the initial build.
When I perform a "POST" request, I get an error. Here is my full code, followed by the error I'm receiving in the Terminal when a "POST" request is submitted.
PS. also fairly new to stack overflow so I'm sorry if I'm asking this question incorrectly
import flask
from flask import Flask, request, jsonify
from flask_uploads import UploadSet, IMAGES, configure_uploads
from flask import make_response
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import turicreate as tc
import sys
from queue import Queue
import os
import uuid
import logging
from flask import send_from_directory
import threading
from marshmallow import fields
from marshmallow import post_load
app = Flask(__name__)
if __name__ == "__main__":
# Only for debugging while developing
app.run(host='0.0.0.0', debug=True)
#configure logging
logging.basicConfig( level=logging.DEBUG,
format='[%(levelname)s] - %(threadName)-10s : %(message)s')
#configure images destination folder
app.config['UPLOADED_IMAGES_DEST'] = './images'
images = UploadSet('images', IMAGES)
configure_uploads(app, images)
#configure sqlite database
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'facerecognition.sqlite')
db = SQLAlchemy(app)
ma = Marshmallow(app)
#model/users is a many to many relationship, that means there's a third #table containing user id and model id
users_models = db.Table('users_models',
db.Column("user_id", db.Integer, db.ForeignKey('user.id')),
db.Column("model_id", db.Integer, db.ForeignKey('model.version'))
)
# model table
class Model(db.Model):
version = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String(100))
users = db.relationship('User', secondary=users_models)
# user table
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(300))
position = db.Column(db.String(300))
def __init__(self, name, position):
self.name = name
self.position = position
#user schema
class UserSchema(ma.Schema):
class Meta:
fields = ('id', 'name', 'position')
#model schema
class ModelSchema(ma.Schema):
version = fields.Int()
url = fields.Method("add_host_to_url")
users = ma.Nested(UserSchema, many=True)
# this is necessary because we need to append the current host to the model url
def add_host_to_url(self, obj):
return request.host_url + obj.url
#initialize everything
user_schema = UserSchema()
users_schema = UserSchema(many=True)
model_schema = ModelSchema()
models_schema = ModelSchema(many=True)
db.create_all()
#error handlers
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'not found'}), 404)
@app.errorhandler(400)
def not_found(error):
return make_response(jsonify({'error': 'bad request'}), 400)
#register user
@app.route("/testImages/face-recognition/api/v1.0/user/register", methods=['POST'])
def register_user():
if not request.form or not 'name' in request.form:
return make_response(jsonify({'status': 'failed', 'error': 'bad request', 'message:' : 'Name is required'}), 400)
else:
name = request.form['name']
position = request.form.get('position')
if position is None:
position = ""
newuser = User(name, position)
db.session.add(newuser)
db.session.commit()
if 'photos' in request.files:
uploaded_images = request.files.getlist('photos')
save_images_to_folder(uploaded_images, newuser)
return jsonify({'status' : 'success', 'user' : user_schema.dump(newuser).data })
#function to save images to image directory
def save_images_to_folder(images_to_save, user):
for a_file in images_to_save:
# save images to images folder using user id as a subfolder name
images.save(a_file, str(user.id), str(uuid.uuid4()) + '.')
# get the last trained model
model = Model.query.order_by(Model.version.desc()).first()
if model is not None:
# increment the version
queue.put(model.version + 1)
else:
# create first version
queue.put(1)
@app.route("/testImages/face-recognition/api/v1.0/model/info" , methods=['GET'])
def get_model_info():
models_schema.context['request'] = request
model = Model.query.order_by(Model.version.desc()).first()
if model is None:
return make_response(jsonify({'status': 'failed', 'error': 'model is not ready'}), 400)
else:
return jsonify({'status' : 'success', 'model' : model_schema.dump(model).data})
#serve models
@app.route('/models/')
def download(filename):
return send_from_directory('models', filename, as_attachment=True)
def train_model():
while True:
#get the next version
version = queue.get()
logging.debug('loading images')
data = tc.image_analysis.load_images('images', with_path=True)
# From the path-name, create a label column
data['label'] = data['path'].apply(lambda path: path.split('/')[-2])
# use the model version to construct a filename
filename = 'Faces_v' + str(version)
mlmodel_filename = filename + '.mlmodel'
models_folder = 'models/'
# Save the data for future use
data.save(models_folder + filename + '.sframe')
result_data = tc.SFrame( models_folder + filename +'.sframe')
train_data = result_data.random_split(0.8)
#the next line starts the training process
model = tc.image_classifier.create(train_data, target='label', model='resnet-50', verbose=True)
db.session.commit()
logging.debug('saving model')
model.save( models_folder + filename + '.model')
logging.debug('saving coremlmodel')
model.export_coreml(models_folder + mlmodel_filename)
# save model data in database
modelData = Model()
modelData.url = models_folder + mlmodel_filename
classes = model.classes
for userId in classes:
user = User.query.get(userId)
if user is not None:
modelData.users.append(user)
db.session.add(modelData)
db.session.commit()
logging.debug('done creating model')
# mark this task as done
queue.task_done()
#configure queue for training models
queue = Queue(maxsize=0)
thread = threading.Thread(target=train_model, name='TrainingDaemon')
thread.setDaemon(False)
thread.start()```
Here is the Error I get In the Terminal
[DEBUG] - TrainingDaemon : loading images
127.0.0.1 - - [03/Jan/2020 11:52:39] "POST /testImages/face-recognition/api/v1.0/user/register HTTP/1.1" 500 -
[INFO] - Thread-3 : 127.0.0.1 - - [03/Jan/2020 11:52:39] "POST /testImages/face-recognition/api/v1.0/user/register HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/me/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/me/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/me/Desktop/GorillaFace/app.py", line 103, in register_user
save_images_to_folder(uploaded_images, newuser)
File "/Users/me/Desktop/GorillaFace/app.py", line 121, in save_images_to_folder
@app.route("/testImages/face-recognition/api/v1.0/model/info" , methods=['GET'])
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1314, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 90, in wrapper_func
"A setup function was called after the "
AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the application where a module was not imported and decorators or other functionality was called too late.
To fix this make sure to import all your view modules, database models and everything related at a central place before the application starts serving requests.
Exception in thread TrainingDaemon:
Traceback (most recent call last):
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/Users/me/Desktop/GorillaFace/app.py", line 159, in train_model
model = tc.image_classifier.create(train_data, target='label', model='resnet-50', verbose=True)
File "/Users/me/venv/lib/python3.7/site-packages/turicreate/toolkits/image_classifier/image_classifier.py", line 225, in create
raise TypeError('"dataset" must be of type SFrame.')
TypeError: "dataset" must be of type SFrame.
What I've tried:
Like I said I'm still new to python so I don't know much about troubleshooting python code. The assertion error seems to be saying something was not imported correctly, so I re-installed, flask-uploads,Flask-SQLAlchemy,flask-marshmallow, marshmallow-sqlalchemy. I also made sure all the imports looked like it did in the tutorial.
Anyone have any ideas as to what I need to do to not get this error? what this code should do is allow me to post a name, position, and photos to the server which will then train a ML model to recognize the new photos.
Error shows in which line it has problem
model = tc.image_classifier.create(...)
and it has problem with
"dataset" must be of type SFrame.
so use at least print()
and print(type(..))
to check variablse which you use in this line and see if you use SFrame
.