Deploy Your Python Functions as a REST API

This tutorial demonstrates how to deploy an arbitrary python function as an api with Bluemix and Flask — complete with clean, intuitive Swagger API documentation. Our python function will be a simple implementation of the Sieve of Eratosthenes, which takes one integer parameter n and returns all primes p such that p <= n.

While completing this tutorial, you will:

  • Create an algorithm (or some arbitrary function) using Notebooks in DSX
  • Persist the function
  • Develop a RESTful API with Swagger documentation using Flask
  • Deploy your API to Bluemix

Implementing the “Sieve of Eratosthenes”

First, we’ll need to create a folder which will contain all of the files needed for our application. I’ll name mine sieve.

!mkdir sieve

Change into that directory and we’ll get started.

cd sieve

The Sieve of Eratosthenes is an ancient prime number sieve which, roughly, finds all the primes up to a given upper bound by striking multiples from the list of candidate primes. The algorithm looks like this:

Let’s write the function in pure python. The exact implementation is not the focus of this article, but it is cool to think about.

def Eratosthenes(upper_bound):
prime = [True] * upper_bound
for p in range(3, upper_bound, 2):
if p > (upper_bound**.5):
break
if prime[p]==True:
for i in range(p * p, upper_bound, 2 * p):
prime[i] = False
return [2] + [p for p in range(3, upper_bound, 2) if
prime[p]]

Testing,

Eratosthenes(22) 
# [2, 3, 5, 7, 11, 13, 17, 19]

We can use some built-in Jupyter magic to write files. We’ll put our function in this file for use later in the application. You can define as many functions as you’d like in this file.

To write, simply prepend this line to the code cell that we want to write %%writefile <file_name>

We’ll name this prime_sieve.py.

%%writefile prime_sieve.py
def Eratosthenes(upper_bound):
prime = [True] * upper_bound
for p in range(3, upper_bound, 2):
if p > (upper_bound**.5):
break
if prime[p]==True:
for i in range(p * p, upper_bound, 2 * p):
prime[i] = False
return [2] + [p for p in range(3, upper_bound, 2) if
prime[p]]

We’ll save this function into a file, so we can make use of it later.

Develop a RESTful API

We’ll use a few tools to develop the API, like Cloud Foundry and Flask. This part of the tutorial is an expansion of a previous guide. From within a Notebook, we can write files and execute shell commands, which means that we can develop the app entirely within DSX notebooks.

%%writefile my_flask_app.py 
from flask import Flask, Response, jsonify
from flask_restplus import Api, Resource, fields, reqparse
from flask_cors import CORS, cross_origin import os
# the app 
app = Flask(__name__)
CORS(app)
api = Api(app, version='1.0', title='APIs for Python Functions', validate=False) ns = api.namespace('primality', 'Returns a list of all primes below a given upper bound')
# load the algo 
from prime_sieve import Eratosthenes as algo
''' We import our function `Erasosthenes` from the file prime_sieve.py. You create all the classes and functions that you want in that file, and import them into the app. ''' 
# model the input data 
model_input = api.model('Enter the upper bound:', { "UPPER_BOUND": fields.Integer(maximum=10e16)})
# the input data type here is Integer. You can change this to whatever works for your app. 
# On Bluemix, get the port number from the environment variable PORT # When running this app on the local machine, default to 8080 
port = int(os.getenv('PORT', 8080)) 
# The ENDPOINT 
@ns.route('/sieve')
# the endpoint 
class SIEVE(Resource):
@api.response(200, "Success", model_input)
@api.expect(model_input)
def post(self):
parser = reqparse.RequestParser()
parser.add_argument('UPPER_BOUND', type=int)
args = parser.parse_args()
inp = int(args["UPPER_BOUND"])
result = algo(inp)
return jsonify({"primes": result})
# run if __name__ == '__main__': app.run(host='0.0.0.0', port=port, debug=False) # deploy with debug=False

Supporting Documents

We’ll need to include some other files in order for our api to behave properly when we try to deploy the app to Bluemix. These files are:

  • manifest.yml, this includes basic information about your app, such as the name and memory
  • setup.py
  • README.md
  • requirements.txt
  • Procfile

We’ll run the following in different cells to create these files.

%%writefile manifest.yml
--- applications:
- name: PRIMALITY_UNIQUE
- random-route: true
- memory: 256M
%%writefile Procfile 
web: python my_flask_app.py
%%writefile README.md 
"Getting Started with Python Algos on Bluemix"
%%writefile requirements.txt 
Flask==0.11.1
cloudant==2.4.0
flasgger==0.6.4
Flask-Cors==3.0.2
Flask-RESTful==0.3.6
flask-restplus==0.9.2
gevent==1.2.1
%%writefile setup.py 
""" Hello World app for deploying Python functions as APIs on Bluemix """
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup( 
name='primality_test',
version='1.0.0',
description='Running Python apps on Bluemix', long_description=long_description,
url='https://github.com/IBM-Bluemix/python-hello-world-flask', license='Apache-2.0'
)
%%writefile LICENSE 
"""Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ..."""

Deploy to Bluemix

Now, we’ll deploy the application to IBM Bluemix. To accomplish this, you’ll need a Bluemix Account. For more information on this part of the tutorial, we have some helpful documentation on deploying an app after it’s been created.

At this point in the tutorial, we have written all of the files needed for our app to run. In order to deploy to Bluemix (and retain the most felixibility when it comes to debugging, etc), I suggest that you copy this notebook and run all the previous cells. If you naviagte to Kernel and select Restart & Run all, this will happen automatically. Then, in your local directory, you'll have all the necessary files to proceed to these next steps.

One alternative is to create the above files yourself with your favorite text editor. If this is the case, then remove the %%writefile magics from the top of the code cells.

Ok, let’s deploy this app. You’ll need basic familiarity with the command line for best results.

  • Install Cloud Foundry command line. This open source service works with Bluemix to deploy apps.
  • Open the terminal or command prompt.

Mac — Click on the finder icon in the top right, search for terminal and open that

Linux — Depends on the distro, but you probably know where it is. In the menu look for accessories.

Windows — Click the start button, search for cmd, open.

  • Log in to Bluemix by running the following command

cf login -a https://api.ng.bluemix.net

  • It will prompt for your username and password.
  • Push the app!

cf push <my_app_name>

Replacing your app name with the name of app in the manifest.yml file. Make sure your app name is unique.

You should run cf apps to check the status of your application.

That’s it!

Testing the API

import requests

& read the docs!

More seriously, you’ve created the docs yourself. 
Take a look by navigating to the url.

Shoutout to Snehal Gawas for her patience and insight regarding this material!


Originally published at datascience.ibm.com on June 20, 2017.