當前位置:
首頁 > 教育 > Python的最快的Web框架快速入門

Python的最快的Web框架快速入門

優效學院,大數據,Java,人工智慧,架構,在線教育


Python的最快的Web框架快速入門

打開今日頭條,查看更多精彩圖片

Sanic是一個和類Flask的基於Python3.5 +的web框架,它編寫的代碼速度特別快。

除了像Flask以外,Sanic還支持以非同步請求的方式處理請求。這意味著你可以使用新的async / await語法,編寫非阻塞的快速的代碼。

既然它說速度特別快,我們先看下官方提供的基準測試結果。

中信高科基準測試

Python的最快的Web框架快速入門

這個測試的程序運行在AWS實例上,系統是Ubuntu,只使用了一個進程。

Sanic的開發者說他們的靈感來自於這篇文章uvloop:快速的Python網路。

那我們就有必要看下uvloop是個什麼庫。


uvloop

uvloop是asyncio默認事件循環的替代品,實現的功能完整,切即插即用.uvloop是用CPython寫的,建於libuv之上

.uvloop可以使asyncio更快。事實上,它至少比nodejs,gevent和其他Python非同步框架要快兩倍。基於uvloop的asyncio的速度幾乎接近了Go程序的速度。


安裝uvloop

uvloop還只能在* nix平台和Python3.5 +以上版本使用。

使用pip安裝:


pip install uvloop

在asyncio代碼中使用uvloop也很簡單:

import asyncio

import uvloop

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

這得代碼使得對任何asyncio.get_event_loop()的調用都將返回一個uvloop實例。

現在我們開始學習中信高科:

安裝Sanic


pip install sanic

創建第一個sanic代碼


from sanic import Sanic

from sanic.response import text

app = Sanic(__name__)

@app.route("/")

async def test(request):

return text("Hello world!")

app.run(host="0.0.0.0", port=8000, debug=True)

如果你熟悉瓶,你會發現,這個語法簡直和瓶一模一樣。


路由(路由)

路由用於把一個函數綁定到一個URL。下面是一些基本的例子:


@app.route("/")

def index():

return text("Index Page")

@app.route("/hello")

def hello():

return text("Hello World")

當然,你還可以動態的變化URL的某些部分,還可以為一個函數指定多個規則。


變數規則

通過把URL的一部分標記為就可以在URL中添加變數。標記的部分會作為關鍵字參數傳遞給函數。通過使用,可以選擇性的加上一個轉換器,為變數指定特定的類型,如果傳入的類型錯誤,Sanic會拋出NotFound異常。請看下面的例子:


from sanic.response import text

@app.route("/tag/<tag>")

async def tag_handler(request, tag):

return text("Tag - {}".format(tag))

@app.route("/number/<integer_arg:int>")

async def integer_handler(request, integer_arg):

return text("Integer - {}".format(integer_arg))

@app.route("/number/<number_arg:number>")

async def number_handler(request, number_arg):

return text("Number - {}".format(number_arg))

@app.route("/person/<name:[A-z]>")

async def person_handler(request, name):

return text("Person - {}".format(name))

@app.route("/folder/<folder_id:[A-z0-9]{0,4}>")

async def folder_handler(request, folder_id):

return text("Folder - {}".format(folder_id))

HTTP請求類型

默認情況下,我們定義的URL只支持GET請求,@ app.route裝飾器提供了一個可選參數方法,這個參數允許傳入所有HTTP方法。

例如:


from sanic.response import text

@app.route("/post", methods=["POST"])

async def post_handler(request):

return text("POST request - {}".format(request.json))

@app.route("/get", methods=["GET"])

async def get_handler(request):

return text("GET request - {}".format(request.args))

也可以簡寫為:


from sanic.response import text

@app.post("/post")

async def post_handler(request):

return text("POST request - {}".format(request.json))

@app.get("/get")

async def get_handler(request):

return text("GET request - {}".format(request.args))

add_route方法

除了@ app.route裝飾器,Sanic還提供了add_route方法。


@ app.route只是包裝了add_route方法。

from sanic.response import text

# Define the handler functions

async def handler1(request):

return text("OK")

async def handler2(request, name):

return text("Folder - {}".format(name))

async def person_handler2(request, name):

return text("Person - {}".format(name))

# Add each handler function as a route

app.add_route(handler1, "/test")

app.add_route(handler2, "/folder/<name>")

app.add_route(person_handler2, "/person/<name:[A-z]>", methods=["GET"])

URL構建

如果可以匹配URL,那麼Sanic可以生成URL嗎?當然可以,url_for()函數就是用於構建指定函數的URL的。它把函數名稱作為第一個參數,其餘參數對應URL中的變數,例如:


@app.route("/")

async def index(request):

# generate a URL for the endpoint `post_handler`

url = app.url_for("post_handler", post_id=5)

# the URL is `/posts/5`, redirect to it

return redirect(url)

@app.route("/posts/<post_id>")

async def post_handler(request, post_id):

return text("Post - {}".format(post_id))

未定義變數會作為網址的查詢參數:


url = app.url_for("post_handler", post_id=5, arg_one="one", arg_two="two")

# /posts/5?arg_one=one&arg_two=two

# 支持多值參數

url = app.url_for("post_handler", post_id=5, arg_one=["one", "two"])

# /posts/5?arg_one=one&arg_one=two

使用藍圖(藍圖)

Sanic也提供了和Flask類似的藍圖.Blueprint

有以下用途:

把一個應用分解為一套藍圖。這是針對大型應用的理想方案:一個項目可以實例化一個應用,初始化多個擴展,並註冊許多藍圖。

在一個應用的URL前綴和(或)子域上註冊一個藍圖.URL前綴和(或)子域的參數成為藍圖中所有視圖的通用視圖參數(預設情況下)。

使用不同的URL規則在應用中多次註冊藍圖。

通過藍圖提供模板過濾器,靜態文件,模板和其他工具。藍圖不必執行應用或視圖函數。


藍圖示例

from sanic import Sanic

from sanic.response import json

from sanic import Blueprint

bp = Blueprint("my_blueprint")

@bp.route("/")

async def bp_root(request):

return json({"my": "blueprint"})

app = Sanic(__name__)

app.blueprint(bp)

app.run(host="0.0.0.0", port=8000, debug=True)

Sanic使用app.blueprint()方法註冊藍圖。

使用藍圖註冊全局中間件


@bp.middleware

async def print_on_request(request):

print("I am a spy")

@bp.middleware("request")

async def halt_request(request):

return text("I halted the request")

@bp.middleware("response")

async def halt_response(request, response):

return text("I halted the response")

使用藍圖處理異常

@bp.exception(NotFound)

def ignore_404s(request, exception):

return text("Yep, I totally found the page: {}".format(request.url))

藍圖使用靜態處理文件

第一個參數指向當前的Python的包

第二個參數的英文靜態文件的目錄


bp.static("/folder/to/serve", "/web/path")

使用url_for

如果要創建頁面鏈接,可以和通常一樣使用url_for()函數,只是要把藍圖名稱作為端點的前綴,並且用一個點(。)來分隔:


@blueprint_v1.route("/")

async def root(request):

url = app.url_for("v1.post_handler", post_id=5) # --> "/v1/post/5"

return redirect(url)

@blueprint_v1.route("/post/<post_id>")

async def post_handler(request, post_id):

return text("Post {} in Blueprint V1".format(post_id))

操作請求數據

對於web應用來說對客戶端向伺服器發送的數據做出相應很重要,在Sanic中由傳入的參數請求來提供請求信息。

為什麼不像Flask一樣提供一個全局變數要求?

Flask是同步請求,每次請求都有一個獨立的新線程來處理,這個線程中也只處理這一個請求。而Sanic是基於協程的處理方式,一個線程可以同時處理幾個,幾十個甚至幾百個請求,把請求作為全局變數顯然會比較難以處理。

請求對象常用參數有


json(any) json body

from sanic.response import json

@app.route("/json")

def post_json(request):

return json({ "received": True, "message": request.json })

args(dict)URL請求參數

?key1 = value1&key2 = value2將轉變為


{"key1": ["value1"], "key2": ["value2"]}

raw_args(dict)和args類似

?key1 = value1&key2 = value2將轉變為


{"key1": "value1", "key2": "value2"}

form(dict)處理POST表單請求,數據是一個字典

body(位元組)處理POST表單請求,數據是一個字元串

其他參數還有:

  • 文件
  • IP
  • 應用
  • 網址
  • 方案
  • 路徑
  • 請求參數

詳細信息參考文檔:請求數據

關於響應

Sanic使用response函數創建響應對象。

  • 文本response.text("你好世界")
  • html response.html("
  • 你好,世界
  • 「)
  • json response.json({"hello":"world"})
  • file response.file("/ srv / www / hello.txt")

from sanic import response

@app.route("/streaming")

async def index(request):

async def streaming_fn(response):

response.write("foo")

response.write("bar")

return response.stream(streaming_fn, content_type="text/plain")

  • 重定向response.file("/ json")
  • raw response.raw("原始數據")
  • 如果想修改響應的頭可以傳入頭參參

from sanic import response

@app.route("/json")

def handle_request(request):

return response.json(

{"message": "Hello world!"},

headers={"X-Served-By": "sanic"},

status=200

)

配置管理

應用總是需要一定的配置的。根據應用環境不同,會需要不同的配置。比如開關調試模式,設置密鑰以及其它依依於環境的東西

.Sanic的設計思路是在應用開始時載入配置。你可以在代碼中直接硬編碼寫入配置,也可以使用配置文件。

不管你使用何種方式載入配置,都可以使用Sanic的配置屬性來操作配置的值.Sanic本身就使用這個對象來保存一些配置,擴展也可以使用這個對象保存配置。同時這也是你保存配置的地方。

配置入門

config實質上是一個字典的子類,可以像字典一樣操作:


app = Sanic("myapp")

app.config.DB_NAME = "appdb"

app.config.DB_USER = "appuser"

也可以一次更新多個配置:

db_settings = {

"DB_HOST": "localhost",

"DB_NAME": "appdb",

"DB_USER": "appuser"

}

app.config.update(db_settings)

從對象導入配置


import myapp.default_settings

app = Sanic("myapp")

app.config.from_object(myapp.default_settings)

使用配置文件

如果把配置放在一個單獨的文件中會更有用。理想情況下配置文件應當放在應用包的外面。這樣可以在修改配置文件時不影響應用的打包與分發

常見用法如下:


app = Sanic("myapp")

app.config.from_envvar("MYAPP_SETTINGS")

首先從myapp.default_settings模塊載入配置,然後根據MYAPP_SETTINGS環境變數所指向的文件的內容重載配置的值。在啟動伺服器前,在Linux或OS X操作系統中,這個環境變數可以在終端中使用export命令來設置:


$ export MYAPP_SETTINGS=/path/to/config_file

$ python myapp.py

部署

Sanic項目還不是特別成熟,現在部署比較簡陋。對Gunicorn的支持也不完善。

詳細信息可以看下這個問題用sanic建造的項目?

先在說下我的部署方式


使用supervisord部署

啟動方式

supervisord -c supervisor.conf


總結

試用了下Sanic,把之前的一個聊天機器人從Flask改成了Sanic。不得不說,如果你有Flask經驗,大致看一下

Sanic的速度比Flask快很多,只是Sanic配套的包還是太少,用於生產環境有一定的風險。



文章中有一些配置文件地址,代碼地址,機器碼地址,由於沒有辦法弄進去,私聊我領取吧 有需要資料的同學也可以來找我!

Python的最快的Web框架快速入門

Python的最快的Web框架快速入門

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!

TAG: |