您好,登錄后才能下訂單哦!
這篇文章主要講解了“flask接口有什么用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“flask接口有什么用”吧!
flask接口調試利器
下面是Flask主頁給我們的第一個例子,我們現在就由它入手,深入理解“@app.route()”是如何工作的。
Python
import flask from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!"
要想明白“@app.route()”的工作原理,我們首先需要看一看Python中的裝飾器(就是以“@”開頭的那玩意,下面接著函數定義)。@app.route和其它裝飾器
究竟什么是裝飾器?沒啥特別的。裝飾器只是一種接受函數(就是那個你用“@”符號裝飾的函數)的函數,并返回一個新的函數。
當你裝飾一個函數,意味著你告訴Python調用的是那個由你的裝飾器返回的新函數,而不僅僅是直接返回原函數體的執行結果。
還不是很明白?這里是一個簡單的例子:
Python
# This is our decorator def simple_decorator(f): # This is the new function we're going to return # This function will be used in place of our original definition def wrapper(): print "Entering Function" f() print "Exited Function" return wrapper @simple_decorator def hello(): print "Hello World" hello()
現在我們有點明白怎樣創建我們自己的“@app.route()”裝飾器了,但你可能會注意到有一個不同點,就是我們的simple_decorator不可以接受任何參數, 但“@app.route()”卻可以。運行上述代碼會輸出以下結果:Entering Function
Hello World
Exited Function
很好!
那么我們怎樣才能給我們的裝飾器傳參數?要實現這個我們只需創建一個“decorator_factory”函數,我們調用這個函數,返回適用于我們函數的裝飾器。現在看看如果實現它。
Python
def decorator_factory(enter_message, exit_message): # We're going to return this decorator def simple_decorator(f): def wrapper(): print enter_message f() print exit_message return wrapper return simple_decorator @decorator_factory("Start", "End") def hello(): print "Hello World" hello()
把“app”放進“app.route”給我們的輸出是:Start
Hello World
End
請注意在我們寫@decorator_factory(“Start”, “End”)時,我們實際調用的是decorator_factory函數,實際返回的裝飾器已經被用上了,代碼很整潔,對吧?
現在我們掌握了裝飾器怎樣工作的全部前置知識 ,可以重新實現Flask API的這個部分了,那么把我們的目光轉移到“app”在我們Flask應用中的重要地位上面來。
在開始解釋Flask對象里面發生了什么之前,我們先創建我們自己的Python類NotFlask。
Python
class NotFlask(): pass app = NotFlask()
Python這不是個很有趣的類,不過有一樣值得注意,就是這個類的方法也可以被用作裝飾器,所以讓我們把這個類寫得更有趣一點,加一個稱作 route的方法,它是一個簡單的裝飾器工廠。
class NotFlask(): def route(self, route_str): def decorator(f): return f return decorator app = NotFlask() @app.route("/") def hello(): return "Hello World!"
這個裝飾器和我們之前創建的那些最大的不同,在于我們不想修改被我們裝飾的函數的行為,我們只是想獲得它的引用。
所以,最后一步是我們打算去利用一個特性,就是用裝飾器函數的副產品去保存一個提供給我們的路徑之間的鏈接,裝飾器函數應該與它關聯起來。
為了實現這個,我們給我們的NotFlask對象加一個“routes”字典,當我們的“decorator”函數被調用,路徑將被插入新字典中函數對應的位置。
Python
class NotFlask(): def __init__(self): self.routes = {} def route(self, route_str): def decorator(f): self.routes[route_str] = f return f return decorator app = NotFlask() @app.route("/") def hello(): return "Hello World!"
Python現在我們就要完成了!可如果沒法訪問內部的視圖函數,保存路徑的字典又有什么用?讓我們加入一個方法serve(path),當給定的路徑存在時運行一個函數并給們我結果,當路徑尚未注冊時則拋出一個異常。
Python在這個系列我們只關注重現那些熱門庫提供的友好API,所以鉤掛“serve”方法實現一個HTTP服務器其實有一點超出本文的范圍,當然結果是確定的,運行下述片段:
class NotFlask(): def __init__(self): self.routes = {} def route(self, route_str): def decorator(f): self.routes[route_str] = f return f return decorator def serve(self, path): view_function = self.routes.get(path) if view_function: return view_function() else: raise ValueError('Route "{}"" has not been registered'.format(path)) app = NotFlask() @app.route("/") def hello(): return "Hello World!"
app = NotFlask() @app.route("/") def hello(): return "Hello World!" print app.serve("/")
我們會看到:
Hello World!
我們已經完成了一個的Flask網頁上第一個例子的非常簡單的重現,讓我們寫一些快速測試檢測我們簡單重現的Flask的“@app.route()”是否正確。
Python
class TestNotFlask(unittest.TestCase): def setUp(self): self.app = NotFlask() def test_valid_route(self): @self.app.route('/') def index(): return 'Hello World' self.assertEqual(self.app.serve('/'), 'Hello World') def test_invalid_route(self): with self.assertRaises(ValueError): self.app.serve('/invalid')
完全正確!所以,僅僅是一個簡單的包含一個字典的裝飾器, 就重現了Flask的“app.route()”裝飾器的基本的行為。吸口氣。
在本系列的下一篇,也是Flask的app.route()的最后一篇,將通過解析下面這個例子來解釋動態URL模式是如何工作。
Python
app = Flask(__name__) @app.route("/hello/<username>") def hello_user(username): return "Hello {} !".format(username)
裝飾器 獲取函數運行時間
def metric(fn): @functools.wraps(fn) def f(arg,**kw): start=round(time.time() 1000) fun=fn(arg,**kw) end=round(time.time() 1000) print('%s executed in %s ms' % (fn.name, end-start)) return fun return f @metric def test1(): time.sleep(0.1) print('hello') @metric def test2(): time.sleep(0.01) print('hello') test1() test2()
from flask import Flask, request app = Flask(__name__) @app.route('/') def hello(): return 'Hello world' if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, port=5555)
本地運行上面代碼,打開瀏覽器訪問 http://localhost:5555/ 就可以看到頁面輸出了 Hello World!
flask 參考鏈接,參考鏈接1,flask中get活post,用postman,postman簡單教程
注意 pi() 的返回值不能是浮點數,所以必須使用 str 轉換成字符串,運行 python flask_pi.py ,打開瀏覽器訪問 http://localhost:5000/pi?n=1000000 ,可以看到頁面輸出 3.14159169866 ,這個值同圓周率已經非常接近。
再仔細觀察代碼,你還會注意到一個特殊的變量 request ,它看起來似乎是一個全局變量。從全局變量里拿當前請求參數,這非常奇怪。如果在多線程環境中,該如何保證每個線程拿到的都是當前線程正在處理的請求參數呢?所以它不能是全局變量,它是線程局部變量,線程局部變量外表上和全局變量沒有差別,但是在訪問線程局部變量時,每個線程得到的都是當前線程內部共享的對象。
from flask import Flask, request,jsonify,url_for app = Flask(__name__) import math import threading class PiCache(object): def __init__(self): self.pis = {} self.lock = threading.RLock() def set(self,n,result): with self.lock: self.pis[n] = result def get(self,n): with self.lock: return self.pis.get(n) cache = PiCache() @app.route('/') def pi(): n = int(request.args.get('n','100')) with app.test_request_context(): print(url_for('pi')) # 返回的是pi函數的URL =route中第一個參數 / result = cache.get(n) if result: return jsonify({'cached':True,'result':result}) s = 0.0 for i in range(1,n): s += 1.0/i/i result = math.sqrt(6*s) cache.set(n,result) return jsonify({'cached':False,'result':result}) if __name__ == '__main__': app.run()
第一次:
{"cached":false,"result":3.1319807472443624}
第二次:
{"cached":true,"result":3.1319807472443624}
from flask import Flask, request,jsonify import redis app = Flask(__name__) import math import threading class PiCache(object): def __init__(self,client): self.client = client def set(self,n,result): self.client.hset('pis',str(n),str(result)) def get(self,n): result = self.client.hget('pis',str(n)) if not result: return return float(result) client = redis.StrictRedis(host='127.0.0.1', port=6379,db = '0') cache = PiCache(client) @app.route('/') def pi(): n = int(request.args.get('n','100')) print(n) result = cache.get(n) if result: return jsonify({'cached':True,'result':result}) s = 0.0 for i in range(1,n): s += 1.0/i/i result = math.sqrt(6*s) cache.set(n,result) return jsonify({'cached':False,'result':result}) if __name__ == '__main__': app.run()
運行 python flask_pi.py ,打開瀏覽器訪問 http://localhost:5000/pi?n=1000000 ,可以看到頁面輸出
第一次結果:
{"cached":false,"result":3.1319807472443624}
第二次結果:
{"cached":true,"result":3.1319807472443624}
重啟進程,再次刷新頁面,可以看書頁面輸出的cached字段依然是true,說明緩存結果不再因為進程重啟而丟失。
MethodView
寫過Django的朋友們可能會問,Flask是否支持類形式的API編寫方式,回答是肯定的。下面我們使用Flask原生支持的MethodView來改寫一下上面的服務。
from flask import Flask, request,jsonify from flask.views import MethodView app = Flask(__name__) import math import threading class PiCache(object): def __init__(self): self.pis = {} self.lock = threading.RLock() def set(self,n,result): with self.lock: self.pis[n] = result def get(self,n): with self.lock: return self.pis.get(n) cache = PiCache() class PiAPI(MethodView): def __init__(self,cache): self.cache = cache def get(self,n): result = self.cache.get(n) if result: return jsonify({'cached':True,'result':result}) s = 0.0 for i in range(1, n): s += 1.0 / i / i result = math.sqrt(6 * s) self.cache.set(n, result) return jsonify({'cached': False, 'result': result}) ''' as_view 提供了參數可以直接注入到MethodView的構造器中 我們不再使用request.args.keys(),而是直接將參數放到URL里面,這就是RESTFUL風格的URL ''' app.add_url_rule('/pi/<int:n>',view_func=PiAPI.as_view('pi',cache)) if __name__ == '__main__': app.run()
然后調用的時候直接在瀏覽器輸入 : http://127.0.0.1:5000/pi/20
結果:
{"cached":false,"result":3.092245052300697}
感謝各位的閱讀,以上就是“flask接口有什么用”的內容了,經過本文的學習后,相信大家對flask接口有什么用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。