This morning, a friend of mine asked me how to write a simple webservice with python. His aim was to use it with fastai models but I will keep it simple here. For such topics, I usually use django but for a single simple webservice, it is a bit too complicated. So I give it a try with flask and here is the result.
The structure
Let’s start by defining our URL and create a simple flask app. Put the following code in app.py:
Here we are. If you run flask run from this file, you’ll see an error because the index.html template is missing.
Let’s fix this error right now! We will be starting with a simple HTML form, with only two inputs:
File selector type=file
Submit button type=submit
You can put this HTML code in your templates/index.html file:
The submit button posts data to /classify URL, which will execute by our classifiy function thanks to the special route decorator.
Now, you can run flask and visit http://127.0.0.1:5000. You can also select some image and submit the form, you’ll see our fixed JSON response.
Starting from now, you can adapt the form and view to your needs.
Read submitted images in python
In my case, I want to get some statistics about the image. So let’s improve the view. First, we’ll have to tell flask where to download the images. For that, you’ll need to pip install Flask-Uploads and then:
to download image in tmp_dir in your server.
To get some statistics about the image, we will use numpy and PIL:
Here we go! You can test this code with several images.
Multiiple image selection
A nice feature is to be able to select and analyse multiple files. It is quite simple, firstly add multiple option to the file input. Then in the python view, replace :
uploaded_files = request.files["image"]
with:
uploaded_files = request.files.getlist("image")
and then you have to perform the analysis on each file with a loop:
for f in uploaded_files:
Error handling
When no images are selected, you can return an empty json, or display an error in the form. For the second solution, here is a way of doing it:
And the error message can be displayed on the form:
Style
Finally, I added some CSS style:
and a small JS code to show the name of the selected file to the user before submiting the form:
Reset selected files
You’ll notice that once the multiple file selection is enabled, if you hit the select files button again, the first selected files will not be deleted but the new files are appended to them. You can add a reset button in your form, e.g. with:
and the corresponding JS:
Conclusion
You’ll notice we have done more than the initial requirement. If you just need the webservice, only the app.py file is needed, together with the tmp_dir directory. Final code in available here:
If you want to post image with the command line, you can use for example:
curl -X POST -H "Content-Type: multipart/form-data" \
-F "image=@my_image.jpg" http://127.0.0.1:5000/classify