Login using Social Account
     Continue with GoogleLogin using your credentials
Now that we witnessed a huge performance advantage with the usage of ZMQ, we shall proceed to make the necessary changes to app.py
such that:
(1) resnet_model_server.py
serves the model predictions. The Server
listens to the port 5576
for any incoming requests.
(2)the client in app.py
sends a request(along with the encoded image) to the Server
for predictions.
(3) the Server
responds to the client in app.py
with the class predictions of the image.
Let us view the files in ~/Flask-ZMQ-App-Folder/Flask-Server-Folder
:
ls ~/Flask-ZMQ-App-Folder/Flask-Server-Folder
We could see app.py
and app_helper.py
.
Previously, it is in app_helper.py
that the model was imported and the predictions are made. Now we no longer need this file, since all this functionality is defined in the RequestHandler
of the resnet_model_server.py
. So we can remove this file.
Remove the file app_helper.py
and rm app_helper.pyc
:
rm app_helper.py
rm app_helper.pyc
Now we shall remove the app.py
so that we could freshly create the file and write the modified code so that we could establish a connection between app.py
and the server.
rm app.py
Freshly create the app.py
using vi
command:
vi app.py
Press i
key and copy-paste the following code into app.py
:
from flask import Flask, request, render_template
from werkzeug.utils import secure_filename
import os
import base64
import uuid
import zmq
# Define a flask app
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route('/uploader', methods = ['POST'])
def upload_file():
predictions=""
if request.method == 'POST':
f = request.files['file']
# Save the file to ./uploads
basepath = os.path.dirname(__file__)
file_path = os.path.join(basepath, 'static','uploads', secure_filename(f.filename))
f.save(file_path)
global img_str
with open(file_path, "rb") as image_file:
img_str = base64.b64encode(image_file.read())
context = zmq.Context()
socket = context.socket(zmq.DEALER)
_rid = "{}".format(str(uuid.uuid4()))
socket.setsockopt(zmq.IDENTITY, _rid)
socket.connect('tcp://localhost:5576')
poll = zmq.Poller()
poll.register(socket, zmq.POLLIN)
obj = socket.send_json({"payload": img_str, "_rid": _rid})
received_reply = False
while not received_reply:
sockets = dict(poll.poll(1000))
if socket in sockets:
if sockets[socket] == zmq.POLLIN:
result_dict = socket.recv_json()
predictions = result_dict['preds']
received_reply = True
return render_template("upload.html", predictions=predictions, display_image=f.filename)
socket.close()
context.term()
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True,port="4114")
Press theesc
key, then :wq
and hit Enter
.
Run the program:
python app.py
Open another web console, and run the resnet_model_server.py
after activating its virtual environment:
cd ~/Flask-ZMQ-App-Folder/Model-Server-Folder
deactivate
source model-env/bin/activate
python resnet_model_server.py
Open a new tab in the browser, and go to http://f.cloudxlab.com:4114/.
We could see that the results are shown up on the browser with very less latency, almost as soon as we submit the image.
Let us have a brief look at the app.py code:
We imported the necessary packages:
from flask import Flask, request, render_template
from werkzeug.utils import secure_filename
import os
import base64
import uuid
import zmq
We define the port number in main method of our program:
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True,port="4114")
We defined the Flask
app for our program.
# Define a flask app
app = Flask(__name__)
We define the default route and function for our web app:
@app.route("/")
def index():
return render_template("index.html")
We define the upload_file
function which is invoked upon submitting the image via UI for predictions:
@app.route('/uploader', methods = ['POST'])
def upload_file():
predictions=""
if request.method == 'POST':
f = request.files['file']
# Save the file to ./uploads
basepath = os.path.dirname(__file__)
file_path = os.path.join(basepath, 'static','uploads', secure_filename(f.filename))
f.save(file_path)
global img_str
with open(file_path, "rb") as image_file:
img_str = base64.b64encode(image_file.read())
context = zmq.Context()
socket = context.socket(zmq.DEALER)
_rid = "{}".format(str(uuid.uuid4()))
socket.setsockopt(zmq.IDENTITY, _rid)
socket.connect('tcp://localhost:5576')
poll = zmq.Poller()
poll.register(socket, zmq.POLLIN)
obj = socket.send_json({"payload": img_str, "_rid": _rid})
received_reply = False
while not received_reply:
sockets = dict(poll.poll(1000))
if socket in sockets:
if sockets[socket] == zmq.POLLIN:
result_dict = socket.recv_json()
predictions = result_dict['preds']
received_reply = True
return render_template("upload.html", predictions=predictions, display_image=f.filename)
socket.close()
context.term()
(1) If there is any POST request, then we are accessing the file in the request:
if request.method == 'POST':
f = request.files['file']
# Save the file to ./uploads
basepath = os.path.dirname(__file__)
file_path = os.path.join(basepath, 'static','uploads', secure_filename(f.filename))
f.save(file_path)
Then we are saving the image in the uploads
folder of static
as already discussed in the previous project.
(2) Nextly, we are reading the image in binary format and then encoding it into base64 form as already discussed while creating the test_client.py
:
global img_str
with open(file_path, "rb") as image_file:
img_str = base64.b64encode(image_file.read())
(3) Then, we create socket, assign the unique id value to it, and connect it to the server which listens to port 5576
:
context = zmq.Context()
socket = context.socket(zmq.DEALER)
_rid = "{}".format(str(uuid.uuid4()))
socket.setsockopt(zmq.IDENTITY, _rid)
socket.connect('tcp://localhost:5576')
(4) We create a roller poll
and register the socket
with it:
poll = zmq.Poller()
poll.register(socket, zmq.POLLIN)
(5) We make a dictionary with the 'payload'
being the encoded image and the '_rid'
being the unique id. We send this in the JSON format to the server using obj = socket.send_json({"payload": img_str, "_rid": _rid})
.
(6) We set the received_reply=False
and keep polling to check if we have messages to receive from the server. Basically, we are waiting for a response from the server.
received_reply = False
while not received_reply:
sockets = dict(poll.poll(1000))
(7) We poll the sockets to check if we have messages to receive and work on it.
if sockets[socket] == zmq.POLLIN:
result_dict = socket.recv_json()
predictions = result_dict['preds']
received_reply = True
If there are, then we receive those JSON messages, and store the predictions in variable predictions
and turn the received_reply
to True
. Once this is True, the loop breaks, and the socket and context close.
Taking you to the next topic in seconds...
Want to create exercises like this yourself? Click here.
No hints are availble for this assesment
Answer is not availble for this assesment
Note - Having trouble with the assessment engine? Follow the steps listed here
Loading comments...