Bladeren bron

committed ipynb

develop
Keith 8 jaren geleden
bovenliggende
commit
4371c9988d
2 gewijzigde bestanden met toevoegingen van 318 en 0 verwijderingen
  1. +43
    -0
      part0_gettingstarted.ipynb
  2. +275
    -0
      part1_flaskwebapi.ipynb

+ 43
- 0
part0_gettingstarted.ipynb Bestand weergeven

@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Getting started with Python and Web APIs in Flask\n",
"\n",
"This tutorial is split into two parts. Part One is a from the ground up tutorial on building a quick and dirty web API (and optionally RESTful) in Python using the [microframework Flask](). Part Two goes into a few of the details of Python data structures assuming you know a few from another language (e.g. Javascript, etc.).\n",
"\n",
"| Part | |\n",
"|:---:|:---|\n",
"|[Part One](./part1_flaskwebapi.ipynb) | Learn how to build a simple Python web API in Flask. |\n",
"|[Part Two](./part2_pythonds.ipynb) | Learn some of the basic Python data structures and Pythonic ways to use them. |\n",
"\n",
"\n",
"Have fun!"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

+ 275
- 0
part1_flaskwebapi.ipynb Bestand weergeven

@@ -0,0 +1,275 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Your first Python REST API server\n",
"\n",
"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:\n",
"\n",
"* how to install/verify your Python installation \n",
"* how to do a basic package installation with `pip`, [Python's package manager](https://en.wikipedia.org/wiki/Pip_(Python))\n",
"* a few common Python data structures (notably Python objects, dictionaries, tuples, lists)\n",
"* how to use the [`json` module](https://docs.python.org/2/library/json.html) in Python\n",
"* how to install the [Flask microframework](http://flask.pocoo.org/) for Python\n",
"* how to build and run a basic API in Flask\n",
"\n",
"#### ADDITIONAL RESOURCES\n",
"\n",
"\n",
"|What | Where | Why |\n",
"|:-------------------:|:----------------------:|:------------------|\n",
"|A nice primer on Python decorators | [https://realpython.com/blog/python/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. |\n",
"|Resource modeling - the RESTful way | [https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling](https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling) | Can't get enough of REST? |\n",
"|A thorough intro to RESTful APIs | [https://codeplanet.io/principles-good-restful-api-design/](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. |\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## STEP 1: Environment check\n",
"\n",
"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.\n",
"\n",
"### CHECK YOUR VERSION OF PYTHON\n",
"1. open terminal and type `python -V`\n",
"```\n",
" $ python -V\n",
" Python 2.7.12 :: Anaconda 4.2.0 (64-bit)\n",
"```\n",
"\n",
"2. execute `pip install flask`\n",
" * if you need to know more about `pip`, please [read more on it](http://www.pythonforbeginners.com/basics/python-pip-usage/). \n",
" \n",
"3. check to see if you have the `json` library installed \n",
" \n",
"```\n",
" $ python\n",
" 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\n",
" Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n",
" Anaconda is brought to you by Continuum Analytics.\n",
" Please check out: http://continuum.io/thanks and https://anaconda.org\n",
" >>> import json\n",
" >>> exit()\n",
"```\n",
"* **If this returns an error please execute `pip install json`.**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Build Your First Example App\n",
"\n",
"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.\n",
"\n",
"1. Open your favorite editor and **create the file `app.py`**.\n",
"\n",
"2. Write the following code in your file and **save it**:\n",
"```python\n",
" # -*- coding: utf-8 -*-\n",
" from flask import Flask\n",
" \n",
" app = Flask(__name__)\n",
"\n",
" if __name__ == \"__main__\":\n",
" app.run()\n",
"```\n",
"\n",
"3. Go to your command line and type:\n",
"```bash\n",
" $ python app.py\n",
"```\n",
"You should see the following:\n",
"```\n",
" * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n",
"``` \n",
"4. Hooray! You have your first Flask app, test it by opening your browser and pointing it to [localhost:5000](http://localhost:5000) (**except if** you don't see that last line `* Running ...`, then something is really wrong!)\n",
"\n",
" 1. **NOTE:** You haven't implemented any endpoints/routes, so you should get HTTP/404 when you hit [localhost:5000](http://localhost:5000). This is the correct behavior.\n",
" 2. The default port is `5000`, which can be changed later.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Let's dissect what is going on ...\n",
"\n",
"line by line now ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"```python\n",
"from flask import Flask\n",
"```\n",
"This is a required import to get any basic Flask app running ... don't forget it, and don't linger on it."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"app = Flask(__name__)\n",
"```\n",
"This variable is necessary to initialize the Flask app -- it is the [Application Object](http://flask.pocoo.org/docs/0.11/api/#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!)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"if __name__ == \"__main__\":\n",
" app.run()\n",
"```\n",
"\n",
"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()`](http://flask.pocoo.org/docs/0.11/api/#flask.Flask.run), which starts the HTTP server (read [the docs carefully if you're deploying](http://flask.pocoo.org/docs/0.11/deploying/#deployment) in a production environment)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## Step 3a: Let's make a few quick changes\n",
"\n",
"\n",
"### Change the port\n",
"\n",
"Let's change the port to something like `5200` using the `port` parameter of the `Flask.run()` method like this:\n",
"```python\n",
"if __name__ == \"__main__\":\n",
" app.run(port=5200)\n",
"```\n",
"### Change the host ipaddress\n",
"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.\n",
"\n",
"Let's put your fixed/assigned/DHCP address in first (remember this _may_ change depending on what network you are on):\n",
"\n",
"* Get the IP of your machine with `ifconfig` (on \\*X) or `ipconfig` on (Win\\*):\n",
"```bash\n",
" $ ifconfig \n",
"```\n",
"\n",
"and make the change accordingly:\n",
"```python\n",
"if __name__ == \"__main__\":\n",
" app.run(_your_ip_address_, port=5200)\n",
"```\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Set DEBUG mode ON\n",
"\n",
"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 ...\n",
"\n",
"And now update your `app.run()` accordingly:\n",
"```python \n",
" app.run(_your_ip_address_, port=5200, debug=True)\n",
"```\n",
"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**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Let's make a route \n",
"\n",
"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:\n",
"\n",
"\n",
"### INGREDIENT A: Some JSON response spec\n",
"\n",
"```json\n",
"{\n",
"\t\"appname\": \"My awesome app\",\n",
"\t\"version\": \"0.1\",\n",
"\t\"creator\": \"BigBird007\"\n",
"}\n",
"```\n",
"\n",
"Because Python dictionaries are *very* similar to JSON objects, we can specify the above JSON like this in Python:\n",
"```python\n",
"data = {\n",
"\t\"appname\": \"My awesome app\",\n",
"\t\"version\": \"0.1\",\n",
"\t\"creator\": \"BigBird007\"\n",
"}\n",
"```\n",
"\n",
"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`). \n",
"\n",
"### INGREDIENT B: A `/status` route and handler \n",
"\n",
"The syntax for specifying a route is\n",
"```python\n",
"@app.route(\"your/route/here\")\n",
"def the_handler_for_the_route():\n",
" # your awesome implementation here\n",
" \n",
" # return some cool JSON usually ... \n",
" return\n",
"```\n",
"\n",
"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](http://flask.pocoo.org/docs/0.11/api/#flask.Flask.route) and here: [http://flask.pocoo.org/docs/0.11/api/#url-route-registrations](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.).\n",
"\n",
"Let's finish off our `/status` route ... make sure you place the route somewhere before the `if __name__ ...` line of code:\n",
"\n",
"\n",
"```python\n",
"@app.route(\"/status\")\n",
"def status_endpoint():\n",
" data = {\n",
" \"appname\": \"My awesome app\",\n",
" \"version\": \"0.1\",\n",
" \"creator\": \"BigBird007\"\n",
" }\n",
" return json.dumps(data)\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Your final code should look like something like the sample file provided in [app.py](./app.py)."
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

Laden…
Annuleren
Opslaan