Sanic原始碼剖析

2021-09-27 04:18:09 字數 4876 閱讀 1083

sanic是乙個可以使用async

/await語法編寫專案的非同步非阻塞框架,它寫法類似於flask,但使用了非同步特性,而且還使用uvloop作為事件迴圈,其底層使用的是libuv,從而使sanic的速度優勢更加明顯。

本章,我將和大家一起看看sanic裡面的執行機制是怎樣的,它的router

blueprint等是如何實現的。

sanic-0.1.2 的核心檔案如下:

.	

├── __init__.py

├── blueprints.py

├── config.py

├── exceptions.py

├── log.py

├── request.py

├── response.py

├── router.py

├── sanic.py

├── server.py

└── utils.py

通過執行下面的示例,這些檔案都會被我們看到它的作用,拭目以待吧,為了方便諸位的理解,我已將我註解的乙份sanic**上傳到了github,見sanic_annotation。

讓我們從******_server開始吧,**如下:

from sanic_0_1_2.src import sanic	

from sanic_0_1_2.src.response import json

async def test(request):

return json()

或許你直接把sanic_annotation專案直接clone到本地比較方便除錯+理解:

git clone 	

cd sanic_annotation/sanic_0_1_2/examples/

那麼,現在一切準備就緒,開始閱讀吧。

前兩行**匯入包:

例項化乙個sanic

=sanic

(__name__

),可見sanic.py,我已經在這個檔案裡面做了一些注釋,這裡也詳細說下sanic類:

其實上面這部分介紹已經講了sanic基本的執行邏輯,如果你理解了,那下面的講解對你來說是輕輕鬆鬆,如果不怎麼明白,也不要緊,這是只是乙個大體的介紹,跟著步驟來,也很容易理解,繼續看**:

# 此處將路由 / 與檢視函式 test 關聯起來	

async def test(request):

return json()

.

route

,上面介紹過,隨著sanic服務的啟動而啟動,可定義引數uri

,methods

目的是為urlpath和檢視函式對應起來,構建一對對映關係,本例中sanic

.router類下的router

.routes

=

會增加乙個名為routenamedtuple,如下:

[route(handler=, methods=none, pattern=re.compile('^/$'), parameters=)]
看到沒,uri

'/'和檢視函式test對應起來了,如果客戶端請求'/',當伺服器監聽到這個請求的時候,handle_request可以通過引數中的request

.url來找到檢視函式test並且執行,隨即生成檢視返回

那麼這裡write_response就會接受檢視函式test返回的json

()

說下router類,這個類的目的就是新增和獲取路由對應的檢視函式,把它想象成dict或許更容易理解:

.run

(host

="0.0.0.0"

,port

=8000

),sanic 下的run函式,啟動乙個http server,主要是啟動run裡面的serve函式,引數如下:

try:	

serve(

host=host,

port=port,

debug=debug,

# 服務開始後啟動的函式

after_start=after_start,

# 在服務關閉前啟動的函式

before_stop=before_stop,

# sanic(__name__).handle_request()

request_handler=self.handle_request,

# 預設讀取config

request_timeout=self.config.request_timeout,

request_max_size=self.config.request_max_size,

) except:

pass

讓我們將目光投向server.py,這也是sanic框架的核心**:

至此,sanic 服務啟動了

不要小看這乙個小小的demo,執行一下,竟然涉及到下面這麼多個檔案,讓我們總結一下:

除去__init__

.pysanic專案一共就10個檔案,這個小demo不顯山不露水地竟然用到了8個,雖然其中幾個沒有怎麼用到,但也足夠說明,你如果理解了這個demo,sanic的執行邏輯以及框架**你已經了解地很深入了

這個例子看完,我們就能輕易地明白什麼是blueprints,以及blueprints的執行方式,**如下:

from sanic_0_1_2.src import sanic	

# 引入blueprint

from sanic_0_1_2.src import blueprint

from sanic_0_1_2.src.response import json, text

blueprint = blueprint('name', url_prefix='/my_blueprint')

blueprint2 = blueprint('name2', url_prefix='/my_blueprint2')

@blueprint.route('/foo')

async def foo(request):

return json()

@blueprint2.route('/foo')

async def foo2(request):

return json()

讓我們從這兩行開始:

blueprint = blueprint('name', url_prefix='/my_blueprint')	

blueprint2 = blueprint('name2', url_prefix='/my_blueprint2')

顯然,blueprint以及blueprint2blueprint根據不同的引數生成的不同的例項物件,接下來要幹嘛?沒錯,分析blueprints.py:

請看下routeregister函式,然後再看下面的**:

# 生成乙個匿名函式到self.deferred_functions列表裡 包含三個引數 handler(foo), uri, methods	

@blueprint.route('/foo')

async def foo(request):

return json()

@blueprint2.route('/foo')

async def foo2(request):

return json()

# 上乙個例子說過這個函式,sanic().register_blueprint() 註冊藍圖

.

run(

host

="0.0.0.0"

,port

=8000

,debug

=true

)服務啟動**不用多說吧?

看到這裡,相信你已經完全理解了sanic的執行機制,雖然還有middleware

&exception的註冊以及呼叫機制沒講,但這和route的執行機制一樣,如果你懂了route那麼這兩個也很簡單。

如果諸位一遍沒怎麼看明白,這裡我建議可以多看幾遍,多結合編輯器debug下原始碼,堅持下來,會發下sanic真的很簡單,當然,這只是第乙個小版本的sanic,和目前的版本相比,不論是**結構的複雜程度以及功能對比,都有很大差距,畢竟,sanic一直在開源工作者的努力下,慢慢成長。

本人技術微末,若有錯誤,請指出,不勝感激.

原始碼剖析 Hashtable 原始碼剖析

hashtable同樣是基於雜湊表實現的,同樣每個元素都是key value對,其內部也是通過單鏈表解決衝突問題,容量不足 超過了閾值 時,同樣會自動增長。hashtable也是jdk1.0引入的類,是執行緒安全的,能用於多執行緒環境中。hashtable同樣實現了serializable介面,它支...

python原始碼剖析 Python原始碼剖析

第頁共 頁python 原始碼剖析 物件機制 1.物件 在python 的世界中,一切都是物件,乙個整數是乙個物件,乙個字串也是 乙個物件,更為奇妙的是,型別也是乙個物件,整數型別是乙個物件,字串類 型也是乙個物件。從 年guido 在那個聖誕節揭開 python 世界的大幕開始,一直到現在,pyt...

Erlang hotwheels原始碼剖析

整體構架 janus transport sup 實質為transport,supervisor,client instance supervisor 每個tcp會話建立乙個transport程序來處理對應客戶端的請求。janus topman sup 實質為topman,worker,topic ...