1 動(dòng)機(jī)
greenlet 包是 Stackless 的副產(chǎn)品,其將微線程稱為 “tasklet” 。tasklet運(yùn)行在偽并發(fā)中,使用channel進(jìn)行同步數(shù)據(jù)交換。
一個(gè)”greenlet”,是一個(gè)更加原始的微線程的概念,但是沒(méi)有調(diào)度,或者叫做協(xié)程。這在你需要控制你的代碼時(shí)很有用。你可以自己構(gòu)造微線程的 調(diào)度器;也可以使用”greenlet”實(shí)現(xiàn)高級(jí)的控制流。例如可以重新創(chuàng)建構(gòu)造器;不同于Python的構(gòu)造器,我們的構(gòu)造器可以嵌套的調(diào)用函數(shù),而被 嵌套的函數(shù)也可以 yield 一個(gè)值。(另外,你并不需要一個(gè)”yield”關(guān)鍵字,參考例子)。
Greenlet是作為一個(gè)C擴(kuò)展模塊給未修改的解釋器的。
1.1 例子
假設(shè)系統(tǒng)是被控制臺(tái)程序控制的,由用戶輸入命令。假設(shè)輸入是一個(gè)個(gè)字符的。這樣的系統(tǒng)有如如下的樣子:
def process_commands(*args): while True: line='' while not line.endswith('/n'): line+=read_next_char() if line=='quit/n': print "are you sure?" if read_next_char()!="y": continue #忽略指令 process_commands(line)
現(xiàn)在假設(shè)你要把程序移植到GUI,而大多數(shù)GUI是事件驅(qū)動(dòng)的。他們會(huì)在每次的用戶輸入時(shí)調(diào)用回調(diào)函數(shù)。這種情況下,就很難實(shí)現(xiàn) read_next_char() 函數(shù)。我們有兩個(gè)不兼容的函數(shù):
def event_keydown(key):
??
def read_next_char():
?? 需要等待 event_keydown() 的調(diào)用
你可能在考慮用線程實(shí)現(xiàn)。而 Greenlet 是另一種解決方案,沒(méi)有鎖和關(guān)閉問(wèn)題。你啟動(dòng) process_commands() 函數(shù),分割成 greenlet ,然后與按鍵事件交互,有如:
def event_keydown(key): g_processor.switch(key)def read_next_char(): g_self=greenlet.getcurrent() next_char=g_self.parent.switch() #跳到上一層(main)的greenlet,等待下一次按鍵 return next_charg_processor=greenlet(process_commands)g_processor.switch(*args)gui.mainloop()
這個(gè)例子的執(zhí)行流程是: read_next_char() 被調(diào)用,也就是 g_processor 的一部分,它就會(huì)切換(switch)到他的父greenlet,并假設(shè)繼續(xù)在頂級(jí)主循環(huán)中執(zhí)行(GUI主循環(huán))。當(dāng)GUI調(diào)用 event_keydown() 時(shí),它切換到 g_processor ,這意味著執(zhí)行會(huì)跳回到原來(lái)掛起的地方,也就是 read_next_char() 函數(shù)中的切換指令那里。然后 event_keydown() 的 key 參數(shù)就會(huì)被傳遞到 read_next_char() 的切換處,并返回。
注意 read_next_char() 會(huì)被掛起并假設(shè)其調(diào)用棧會(huì)在恢復(fù)時(shí)保護(hù)的很好,所以他會(huì)在被調(diào)用的地方返回。這允許程序邏輯保持優(yōu)美的順序流。我們無(wú)需重寫 process_commands() 來(lái)用到一個(gè)狀態(tài)機(jī)中。
2 使用
2.1 簡(jiǎn)介
一個(gè) “greenlet” 是一個(gè)很小的獨(dú)立微線程。可以把它想像成一個(gè)堆棧幀,棧底是初始調(diào)用,而棧頂是當(dāng)前greenlet的暫停位置。你使用greenlet創(chuàng)建一堆這樣的堆 棧,然后在他們之間跳轉(zhuǎn)執(zhí)行。跳轉(zhuǎn)不是絕對(duì)的:一個(gè)greenlet必須選擇跳轉(zhuǎn)到選擇好的另一個(gè)greenlet,這會(huì)讓前一個(gè)掛起,而后一個(gè)恢復(fù)。兩 個(gè)greenlet之間的跳轉(zhuǎn)稱為 切換(switch) 。
新聞熱點(diǎn)
疑難解答
圖片精選