python 異步Web框架sanic
我們繼續學習Python異步編程,這裏將介紹異步Web框架sanic,爲什麼不是tornado?從框架的易用性來說,Flask要遠遠比tornado簡單,可惜flask不支持異步,而sanic就是類似Flask語法的異步框架。
github:https://github.com/huge-success/sanic
不過sanic對環境有要求:
macOS/linux
python 3.6+
不過,我在macOS上安裝 sanic 還是踩了坑。依賴庫ujson一直安裝失敗。最後不得不卸載官方python,安裝 miniconda(第三方Python安裝包,集成了一些額外的工具)。
安裝 sanic
pip3 install sanic
sanic 開發第一個例子
編寫官方的第一個例子hello.py:
from sanic import Sanic
from sanic.response import json
from sanic.exceptions import NotFound
app = Sanic(name="pyapp")
@app.route('/')
async def test(request):
return json({'hello': 'world'})
if name == '__main__':
app.error_handler.add(
NotFound,
lambda r, e: sanic.response.empty(status=404)
)
app.run(host='0.0.0.0', port=8000)
運行上面的程序:
python3 hello.py
[2020-04-21 23:12:02 +0800] [18487] [INFO] Goin Fast @ http://0.0.0.0:8000
[2020-04-21 23:12:02 +0800] [18487] [INFO] Starting worker [18487]
通過瀏覽器訪問:http://localhost:8000/
請求堵塞
針對上面的例子,假設test() 視圖函數的處理需要5秒鐘,那麼請求就堵塞了。
……
from time import sleep
app = Sanic(name="pyapp")
@app.route('/')
async def test(request):
sleep(5)
return json({'hello': 'world'})
……
重啓服務,通過瀏覽器發送請求,我們發現請求耗時5秒,這顯然對用戶就不能忍受的。
異步非堵塞
所以,我們要實現異步調用,修改後的完整代碼如下:
import asyncio
from sanic import Sanic
from sanic.response import json
from sanic.exceptions import NotFound
from time import sleep, ctime
app = Sanic(name="pyapp")
async def task_sleep():
print('sleep before', ctime())
await asyncio.sleep(5)
print('sleep after', ctime())
@app.route('/')
async def test(request):
myLoop = request.app.loop
myLoop.create_task(task_sleep())
return json({'hello': 'world'})
if name == '__main__':
app.error_handler.add(
NotFound,
lambda r, e: sanic.response.empty(status=404)
)
app.run(host='0.0.0.0', port=8000)
關於python異步的使用參考上一篇文章,重新啓動服務。這次前端就不在堵塞了。
如果看 sanic 的運行日誌:
sleep before Tue Apr 21 23:43:14 2020
sleep after Tue Apr 21 23:43:19 2020
他仍然在執行,但不會堵塞test()視圖函數的響應。