一個最小的API
以下定義了一個簡單的get和post請求
get請求,返回Hello World!
post請求,發送任務信息的json數據,如:{“id”:“1”,“info”:“firstTask”},服務根據請求傳輸的json數據生成任務並添加到任務列表
import json
from flask import Flask, abort, request, jsonify
app = Flask(__name__)#創建實例
tasks = []
#無參接口
@app.route('/HelloWorld')
def hello_world():
return "Hello World!"
@app.route('/addTask/', methods=['POST'])
def add_task():
if not request.json or 'id' not in request.json or 'info' not in request.json:
abort(400)
task = {'id': int(request.json['id']),'info': request.json['info']}#獲取post請求參數,request.json[]
tasks.append(task)#添加任務到任務列表
return jsonify({'result': 'success'})
if __name__ == '__main__':
app.run(debug=True) # 可以設置ip和端口,默認5000端口
flask-restful
Flask-RESTful 提供的最主要的基礎就是資源(resources)。資源(Resources)是構建在 Flask 可拔插視圖 之上,只要在你的資源(resource)上定義方法就能夠容易地訪問多個 HTTP 方法。主要體現在可以設置一個url的不同請求方式對應的操作,而無需自定義多個接口路由信息。
from flask import Flask, request
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
todos = {}
class TodoSimple(Resource):
def get(self, todo_id):
return {todo_id: todos[todo_id]}
def put(self, todo_id):
todos[todo_id] = request.form['data']
return {todo_id: todos[todo_id]}
api.add_resource(TodoSimple, '/<string:todo_id>')
if __name__ == '__main__':
app.run(debug=True)
上述代碼TodoSimple就是一個資源,在這個資源下,我們可以定義多個方法,上述代碼定義了get put兩個方法,get請求根據路徑中的"todo_id"獲取todos字典中相應值,put請求補充todos中相應值並返回。
測試
python自帶的requests庫
from requests import put, get
put('http://localhost:5000/todo1', data={'data': 'test data'}).json()
# output
{'id1': 'test data'}
通過curl
curl http://localhost:5000/todo1 -d "data=test data" -X PUT # put
curl http://127.0.0.1:5000/todo1 -I # get
endpoint 端點
很多時候在一個API中,你的資源可以通過多個URL訪問。你可以把多個URL傳給Api對象的add_resource()方法。每一個URL可以訪問到你的資源。這裏的對應關係爲,URL對應到端點,端點對應到具體的視圖函數。
Flask中endpoint的理解
api.add_resource(HelloWorld,
'/',
'/hello')
參數解析
Flask-RESTful內置了支持驗證請求數據,它使用了一個類似argparse的庫。(返回字典)
from flask_restful import reqparse
parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate to charge for this resource')
args = parser.parse_args()
如果一個參數沒有通過校驗,則Flask-RESTful將以一個400的錯誤請求以及高亮的錯誤信息響應。
輸入模塊提供許多常用的轉換函數,像inputs.date()和inputs.url()。
調用parse_args強制strict = True能夠確保當請求包含了你的解析器中未定義的參數時引發一個異常。
app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('num', type=int, help='number')
todos = {}
class TodoSimple(Resource):
def get(self, todo_id):
return {todo_id: todos[todo_id]}
def put(self, todo_id):
args = parser.parse_args(strict=True)
todos[todo_id] = request.form['num']
return {todo_id: todos[todo_id]}
api.add_resource(TodoSimple, '/<string:todo_id>')
if __name__ == '__main__':
app.run(debug=True)
127.0.0.1 - - [12/Jun/2020 14:32:07] "PUT /id1 HTTP/1.1" 400 -
使用gevent
Flask 是單線程運行,如果在某個頁面中執行了一些耗時的工作,那麼程序就會在這裏等待,無法響應其他的請求
考慮使用 gevent 非阻塞的運行服務器程序。在引入 gevent 前,可以在程序最開始執行的位置引入猴子補丁 gevent.monkey,這能修改 python 默認的 IO 行爲,讓標準庫變成協作式(cooperative)的 API。注意引入 gevent 後,不能再用原來的方式啓動我們的 web 應用了
# app.py
from gevent import monkey
monkey.patch_all() # 打上猴子補丁
from flask import flask
...
if __name__ == '__main__':
from gevent import pywsgi
app.debug = True
server = pywsgi.WSGIServer( ('127.0.0.1', 5000 ), app )
server.serve_forever()
這塊不詳細描述,有需要
在 Flask 應用中使用 gevent
WARNING: This is a development server. Do not use it in a production deployment. falsk WSGI
Error
調試程序經常會遇到:OSError: [Errno 98] Address already in use
,這是因爲上次程序的進程沒有停止
通過 netstat -tunlp
獲取被佔用的地址和端口的進程id pid
通過kill -9 pid
,停掉該進程
建議停止程序通過Ctrl + C
而不是Ctrl + Z
OSError: [Errno 98] Address already in use解決辦法
未完待續…
主要參考
Flask擴展系列之Flask-RESTful
Python中Flask-RESTful編寫API接口—小白入門詳解