Talk given to full stack cohort at Galvanize/Boulder on December 20, 2016 about building APIs with Python / Flask.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

part1_flaskwebapi.md 7.8 KiB

пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. # Your first Python API server
  2. 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:
  3. * how to install/verify your Python installation
  4. * how to do a basic package installation with `pip`, [Python's package manager](https://en.wikipedia.org/wiki/Pip_(Python))
  5. * a few common Python data structures (notably Python objects, dictionaries, tuples, lists)
  6. * how to use the [`json` module](https://docs.python.org/2/library/json.html) in Python
  7. * how to install the [Flask microframework](http://flask.pocoo.org/) for Python
  8. * how to build and run a basic API in Flask
  9. #### ADDITIONAL RESOURCES
  10. |What | Where | Why |
  11. |:-------------------:|:----------------------:|:------------------:|
  12. |A nice primer on Python decorators | [http://bit.ly/25ij4gY](http://bit.ly/25ij4gY) | You might want to get a little under the hood on how the routes (and other) decorators work. |
  13. ## STEP 1: Environment check
  14. 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.
  15. ### CHECK YOUR VERSION OF PYTHON
  16. 1. open terminal and type `python -V`
  17. ```
  18. $ python -V
  19. Python 2.7.12 :: Anaconda 4.2.0 (64-bit)
  20. ```
  21. 2. execute `pip install flask`
  22. * if you need to know more about `pip`, please [read more on it](http://www.pythonforbeginners.com/basics/python-pip-usage/)
  23. 3. check to see if you have json installed
  24. ```
  25. $ python
  26. 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
  27. Type "help", "copyright", "credits" or "license" for more information.
  28. Anaconda is brought to you by Continuum Analytics.
  29. Please check out: http://continuum.io/thanks and https://anaconda.org
  30. >>> import json
  31. >>> exit()
  32. ```
  33. * **If this returns an error please execute `pip install json`.**
  34. ## Step 2: Build Your First Example App
  35. 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.
  36. 1. Open your favorite editor and **create the file `app.py`**.
  37. 2. Write the following code in your file and **save it**:
  38. ```python
  39. # -*- coding: utf-8 -*-
  40. from flask import Flask
  41. app = Flask(__name__)
  42. if __name__ == "__main__":
  43. app.run()
  44. ```
  45. 3. Go to your command line and type:
  46. ```bash
  47. $ python app.py
  48. ```
  49. You should see the following:
  50. ```
  51. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
  52. ```
  53. 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!)
  54. 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.
  55. 2. The default port is `5000`, which can be changed later.
  56. ## Step 3: Let's dissect what is going on ...
  57. line by line now ...
  58. ```python
  59. from flask import Flask
  60. ```
  61. This is a required import to get any basic Flask app running ... don't forget it, and don't linger on it.
  62. ```python
  63. app = Flask(__name__)
  64. ```
  65. 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!)
  66. ```python
  67. if __name__ == "__main__":
  68. app.run()
  69. ```
  70. 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).
  71. ## Step 3a: Let's make a few quick changes
  72. ### Change the port
  73. Let's change the port to something like `5200` using the `port` parameter of the `Flask.run()` method like this:
  74. ```python
  75. if __name__ == "__main__":
  76. app.run(port=5200)
  77. ```
  78. ### Change the host ipaddress
  79. 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.
  80. Let's put your fixed/assigned/DHCP address in first (remember this _may_ change depending on what network you are on):
  81. * Get the IP of your machine with `ifconfig` (on \*X) or `ipconfig` on (Win\*):
  82. ```bash
  83. $ ifconfig
  84. ```
  85. and make the change accordingly:
  86. ```python
  87. if __name__ == "__main__":
  88. app.run(_your_ip_address_, port=5200)
  89. ```
  90. ### Set DEBUG mode ON
  91. 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 ...
  92. And now update your `app.run()` accordingly:
  93. ```python
  94. app.run(_your_ip_address_, port=5200, debug=True)
  95. ```
  96. 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**.
  97. ## Step 4: Let's make a route
  98. 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:
  99. ### INGREDIENT A: Some JSON response spec
  100. ```json
  101. {
  102. "appname": "My awesome app",
  103. "version": "0.1",
  104. "creator": "BigBird007"
  105. }
  106. ```
  107. Because Python dictionaries are *very* similar to JSON objects, we can specify the above JSON like this in Python:
  108. ```python
  109. data = {
  110. "appname": "My awesome app",
  111. "version": "0.1",
  112. "creator": "BigBird007"
  113. }
  114. ```
  115. 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 a JSON string (`dumps`) and from a JSON object to a Python object (`loads`) so
  116. ### INGREDIENT B: A `/status` route and handler
  117. The syntax for specifying a route is
  118. ```python
  119. @app.route("your/route/here")
  120. def the_handler_for_the_route():
  121. # your awesome implementation here
  122. # return some cool JSON usually ...
  123. return
  124. ```
  125. 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.).
  126. Let's finish off our `/status` route ... make sure you place the route somewhere before the `if __name__ ...` line of code:
  127. ```python
  128. @app.route("/status")
  129. def status_endpoint():
  130. data = {
  131. "appname": "My awesome app",
  132. "version": "0.1",
  133. "creator": "BigBird007"
  134. }
  135. return json.dumps(data)
  136. ```
  137. Your final code should look like something like the sample file provided in [app.py](./app.py).
  138. ```python
  139. %pastebin -d "v0.1 gSchool Talk" gSchoolWinter16_PythonFlaskApp.md
  140. ```
  141. u'https://gist.github.com/8c90a3673f6e44ac30f2891155f4f74c'