In this tutorial you will learn how to make a simple HTTP/REST API in Python 2.7 (or 3.5). When you're done you will know about:
pip
, Python's package manager)json
module in PythonWhat | Where | Why |
---|---|---|
A nice primer on Python decorators | https://realpython.com/blog/python/primer-on-python-decorators/ | You might want to get a little under the hood on how the routes (and other) decorators work. |
Resource modeling - the RESTful way | https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling | Can't get enough of REST? |
A thorough intro to RESTful APIs | https://codeplanet.io/principles-good-restful-api-design/ | This really nails the full spectrum of concerns in a nice way, but get some coffee before you start. |
You will minimally need Python 2.7.1x for this tutorial. Most if not all of the code will work in 3.5.x as well, so feel free to use that moving forward.
open terminal and type python -V
$ python -V
Python 2.7.12 :: Anaconda 4.2.0 (64-bit)
execute pip install flask
pip
, please read more on it. check to see if you have the json
library installed
$ python
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> import json
>>> exit()
pip install json
.We're now going to build our first functional app. It isn't going to do anything yet -- we just want to make sure that we can see that everything is looking good in our environment.
Open your favorite editor and create the file app.py
.
Write the following code in your file and save it:
# -*- coding: utf-8 -*- from flask import Flask app = Flask(__name__) if __name__ == "__main__": app.run()
Go to your command line and type:
$ python app.py
You should see the following:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Hooray! You have your first Flask app, test it by opening your browser and pointing it to localhost:5000 (except if you don't see that last line * Running ...
, then something is really wrong!)
5000
, which can be changed later.line by line now ...
from flask import Flask
This is a required import to get any basic Flask app running ... don't forget it, and don't linger on it.
app = Flask(__name__)
This variable is necessary to initialize the Flask app -- it is the Application Object. We're giving the name __name__
because we are running this application as a standalone in a single file (app.py
). You can read more about how Python handles application and module name spaces, but if a file you create is run from the command line, its application __name__
attribute will be set to __main__
(unless overridden by the developer, but that is not a typical move in Python, so don't go playing footsy with it until you know why you might want to do so!)
if __name__ == "__main__": app.run()
This last bit of code tells Python that if this file is run from the command line (as opposed to being imported as a module), then execute the Flask application method run()
, which starts the HTTP server (read the docs carefully if you're deploying in a production environment).
Let's change the port to something like 5200
using the port
parameter of the Flask.run()
method like this:
if __name__ == "__main__": app.run(port=5200)
The default parameter for the run()
method is indeed the IP of your running server (which defaults to 127.0.0.1
). You can set it to your fixed IP or use 0.0.0.0
to make it externally available.
Let's put your fixed/assigned/DHCP address in first (remember this may change depending on what network you are on):
ifconfig
(on *X) or ipconfig
on (Win*):$ ifconfig
and make the change accordingly:
if __name__ == "__main__": app.run(_your_ip_address_, port=5200)
Finally, let's make sure we run in debug mode so if anything crazy happens, we can find out what ... using the debug
parameter makes that a snap ...
And now update your app.run()
accordingly:
app.run(_your_ip_address_, port=5200, debug=True)
With this, others will be able to see your server (on the same network) and you will be able to make changes to your code and dynamically update your code without stopping and starting the server.
In our final step, we're going to implement something interesting (well sort of anyway). Let's say we have an application which will respond to /status
by returning the following json:
{ "appname": "My awesome app", "version": "0.1", "creator": "BigBird007" }
Because Python dictionaries are very similar to JSON objects, we can specify the above JSON like this in Python:
data = { "appname": "My awesome app", "version": "0.1", "creator": "BigBird007" }
To convert this Python dictionary to JSON so we can return it over the wire, we use the json
library. The two methods you should just remember are json.dumps(a_python_object)
and json.loads(a_json_string)
... these two methods allow you to go back and forth from Python to a JSON string (dumps
) and from a JSON object (as a string) back to a Python object (loads
).
/status
route and handler¶The syntax for specifying a route is
@app.route("your/route/here") def the_handler_for_the_route(): # your awesome implementation here # return some cool JSON usually ... return
This pattern will be used over and over in your code, study it and remember it. To learn how to use this pattern to specify things like your GET
or POST
handlers, read the docs further here: http://flask.pocoo.org/docs/0.11/api/#flask.Flask.route and here: http://flask.pocoo.org/docs/0.11/api/#url-route-registrations. Everything you'd want to know will be there (including handling variable parts of your route, defaults, method handling, etc.).
Let's finish off our /status
route ... make sure you place the route somewhere before the if __name__ ...
line of code:
@app.route("/status") def status_endpoint(): data = { "appname": "My awesome app", "version": "0.1", "creator": "BigBird007" } return json.dumps(data)
Your final code should look like something like the sample file provided in app.py.