eventlet學習筆記
標簽(空格分隔): python eventlet
eventlet是一個用來處理和網絡相關的python庫函數,且可以通過協程(coroutines)實現並發。在eventlet里,將協程叫做greenthread(綠色線程),所謂並發,即開啟多個greenthread,並對這些greenthread進行管理。尤為方便的是,eventlet為了實現“綠色線程”,竟然對python的和網絡相關的幾個標准庫函數進行了改寫,並且可以以補丁(patch)的方式導入到程序中,因為python的庫函數只支持普通的線程,而不支持協程,eventlet稱之為“綠化”。
eventlet主要基於兩個庫——greenlet(過程化其並發基礎,簡單封裝后即成為GreenTread)和select.epoll(默認網絡通信模型)。
1.greenlet
greenlet支持微線程(tasklet),tasklet偽並發運行,同步在信道上交換數據。
greenlet——coroutines(協程)——micro-thread(微線程)(三者意思相近)
在greenlet上可自定義微線程調度順序,靈活掌控控制流。
(1)greenlet簡介
greenlet之間可相互切換,當一個greenlet1切換至greenlet2時,greenlet1掛起,當greenlet2運行一段時候切換回時,greenlet2掛起,greenlet1恢復運行。
每個greenlet創建時擁有一個空的棧,當切換至該greenlet時,它會運行一個特殊函數(該函數也許會調用其它函數),當最終最外層函數執行完成后,greenlet棧再次為空,greenlet死亡。greenlet也可被不可捕捉的異常殺死。
(2)Parents
每一個greenlet有一個父greenlet,相應父greenlet在greenlet被創建時初始化。greenlet死亡后,父greenlet繼續執行。
greenlet樹形組織,隱含的main greenlet為此樹根節點。任何一個greenlet死亡,執行順序將被回溯至main greenlet。異常發生將傳播至parent greenlet。
switch不是調用,只是在並行的'stack containers'中傳輸執行。
(3)實例化
greenlet類型greenlet.greenlet,有如下一些方法:
greenlet(run=None, parent=None)
創建一個新的greenlet對象但並不運行,run為可調用請求,parent為父greenlet,默認為當前greenlet。
greenlet.getcurrent()
返回當前greenlet。
greenlet.GreenletExit
此特殊異常不會傳播至父greenlet,它被用於殺死一個單獨的greenlet。
(4)切換
greenlet切換發生在switch()函數被調用或一個greenlet死亡時。調用switch
()函數的greenlet為切換至的目標greenlet;greenlet死亡時切換至parent greenlet。切換時,一個對象或異常發送至目標greenlet,這即是greenlets間方便的通信方式。例如:
def test1(x, y):
z = gr2.switch(x+y)
print z
def test2(u):
print u
gr1.switch(42)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch("hello", " world")
此段程序輸出“hello world”和42.需注意test1()和test2()的參數並不是在greenlet創建時給出,而是在第一次切換到相應greenlet時給出。
g.switch(*args, **kwargs)
切換至greenlet g執行。
需要注意的是x = g.switch(y)
,會將對象y發送給g,然而稍后卻有可能將毫無關聯的對象經毫無關聯的greenlet處理后返回給x。這可以理解為g.switch(y)的值沒有立即返回,而其它greenlet的結果卻先返回了!!!
switch至一個已經死亡的greenlet,最終將會switch至其parent greenlet或parent' parent greenlet,如此回溯。(最終的parent greenlet是main greenlet,永不死亡。)
(5)greenlets方法和屬性
g.switch(*args, **kwargs)
切換至greenlet g執行。
g.run
執行后運行greenlet g,g運行后該屬性不再存在。
g.parent
g的parent greenlet。該變量可寫,但禁止構造循環型父子關系。
g.gr_frame
目前上層框架,或為None。
g.dead
當g死亡時值為True。
bool(g)
g處於活動狀態時值為True,若死亡或還未開始值為False。
g.throw([typ, [val, [tb]]])
切換執行序列至greenlet g,在g中立即拋出給定異常。若未提供參數,異常默認為greenlet.GreenletExit。
(6)Greenlet和python線程
Greenlet能夠和Python線程結合,每個python線程中包含一個獨立的main greenlet及由其子greenlet構成的樹。但不屬於同一個線程的不同greenlet之間不能結合或切換。
參考文章:
【1】Eventlet documentation
【2】Openstack eventlet分析——溜溜小哥的CSDN博客