Flask 初識

一個最小的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接口—小白入門詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章