摘要:協(xié)程其實(shí)就是一個(gè)可中途中斷,由外部來(lái)控制執(zhí)行進(jìn)程的函數(shù)。這些第三方的選擇的共同特點(diǎn)是協(xié)程的都是隱式的。這就是顯示控制和隱式控制的區(qū)別。本文討論的協(xié)程就是這一種,后面會(huì)逐漸展開(kāi)到如何利用這種顯示控制的協(xié)程來(lái)解決阻塞和流程阻塞的問(wèn)題。
Python官方的實(shí)現(xiàn)里,協(xié)程只有g(shù)enerator這一招。協(xié)程其實(shí)就是一個(gè)可中途中斷,由外部來(lái)控制執(zhí)行進(jìn)程的函數(shù)。除了官方的generator,還有很多第三方的實(shí)現(xiàn)可以選擇。常見(jiàn)的第三方選擇有:
Greenlet,基于Python的常規(guī)版本(CPython)的C擴(kuò)展實(shí)現(xiàn)
Stackless Python,是一個(gè)修改版本的Python解釋器,支持tasklet api
Pypy,是一個(gè)修改版本的Python解釋器,支持continulet api。它還基于此實(shí)現(xiàn)了模擬Greenlet和Stackless的上層api。
這些第三方的選擇的共同特點(diǎn)是協(xié)程的都是隱式的。比如,使用基于Greenlet的gevent,調(diào)用http api的時(shí)候,可能代碼寫(xiě)起來(lái)是這樣的
urllib2.urlopen("http://www.google.com")
表面上看上去就是一個(gè)普通的函數(shù)調(diào)用,但是內(nèi)部可能是
urlopen => http call => tcp socket open => create socket, register fd on event loop
最終在最內(nèi)層,把當(dāng)前的協(xié)程的控制權(quán)交出去了,讓event loop去回調(diào)當(dāng)前的協(xié)程。也就是說(shuō)urlopen這個(gè)函數(shù)調(diào)用可能導(dǎo)致當(dāng)前執(zhí)行的協(xié)程發(fā)生變化,而作為調(diào)用方可能根本不知情,除非你了解urlopen內(nèi)層的所有實(shí)現(xiàn),這就叫隱式的。
反觀generator,只要當(dāng)前的語(yǔ)句沒(méi)有關(guān)鍵字“yield”,你就可以非常放心的認(rèn)為當(dāng)前這句話不會(huì)跳出當(dāng)前協(xié)程,而會(huì)連續(xù)地執(zhí)行下去。這個(gè)是一個(gè)優(yōu)點(diǎn),可以讓代碼變得更好理解,更不容易出因?yàn)閳?zhí)行順序不同修改共享狀態(tài)造成bug。但也是一個(gè)缺點(diǎn),傳統(tǒng)的沒(méi)有yield的代碼是無(wú)法“自動(dòng)”地“魔法般”地享受一些一步框架可能帶來(lái)的好處。比如說(shuō):
def process(): for i in sub_process(): yield i def sub_process(): yield 1 yield 2 yield 3 print(list(process()))
process不會(huì)因?yàn)檎{(diào)用了sub_process(),而sub_process()內(nèi)又有yield就會(huì)自動(dòng)交出當(dāng)前協(xié)程的執(zhí)行權(quán),不會(huì)的。process如果想要交出執(zhí)行權(quán),必須自己再次yield。這就是顯示控制和隱式控制的區(qū)別。本文討論的協(xié)程就是generator這一種,后面會(huì)逐漸展開(kāi)到如何利用這種顯示控制的協(xié)程來(lái)解決I/O阻塞和流程阻塞的logic locality問(wèn)題。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/37379.html
摘要:比如里可以直接把執(zhí)行權(quán)交給,而完全不知情。雖然不能和多線程相比,但是效果是類似的。對(duì)于多線程的代碼,是任何一行代碼都可能與其他線程并行。加上協(xié)程之間有共享狀態(tài)的話,一定程度上會(huì)產(chǎn)生類似多線程的并發(fā)讀寫(xiě)狀態(tài)的。 前面講generator是顯式的協(xié)程的時(shí)候缺一個(gè)例子,現(xiàn)在補(bǔ)上 def parent_generator(): print(hello) yield from ...
摘要:如果說(shuō)相比來(lái)說(shuō),是一種隱式的協(xié)程的話,提供的就更加隱式了。通過(guò)調(diào)用可以知道這個(gè)鏈表目前的大小。正式因?yàn)闆](méi)有把底層的協(xié)程直接控制接口開(kāi)放,而是強(qiáng)買(mǎi)強(qiáng)賣(mài)了一個(gè),所以想要在像那樣隨心所欲的操縱協(xié)程還是頗費(fèi)一番周折的。 如果說(shuō)greenlet相比generator來(lái)說(shuō),是一種隱式的協(xié)程的話,stackless python提供的api就更加隱式了。 import stackless def...
摘要:協(xié)程的基本行為協(xié)程包含四種狀態(tài)等待開(kāi)始執(zhí)行。協(xié)程中重要的兩個(gè)方法調(diào)用方把數(shù)據(jù)提供給協(xié)程。注意使用調(diào)用協(xié)程時(shí)會(huì)自動(dòng)預(yù)激,因此與裝飾器不兼容標(biāo)準(zhǔn)庫(kù)中的裝飾器不會(huì)預(yù)激協(xié)程,因此能兼容句法。因此,終止協(xié)程的本質(zhì)在于向協(xié)程發(fā)送其無(wú)法處理的異常。 導(dǎo)語(yǔ):本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之控制流程篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門(mén)Python的朋友們可以來(lái)一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、掌握協(xié)...
摘要:本文先回顧生成器,然后過(guò)渡到協(xié)程編程。其作用主要體現(xiàn)在三個(gè)方面數(shù)據(jù)生成生產(chǎn)者,通過(guò)返回?cái)?shù)據(jù)數(shù)據(jù)消費(fèi)消費(fèi)者,消費(fèi)傳來(lái)的數(shù)據(jù)實(shí)現(xiàn)協(xié)程。解決回調(diào)地獄的方式主要有兩種和協(xié)程。重點(diǎn)應(yīng)當(dāng)關(guān)注控制權(quán)轉(zhuǎn)讓的時(shí)機(jī),以及協(xié)程的運(yùn)作方式。 轉(zhuǎn)載請(qǐng)注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請(qǐng)求 cookie web響應(yīng) sess...
摘要:常規(guī)版本的的是不可以被持久化保存的。在流程被阻塞的時(shí)候比如需要審批老板不在把協(xié)程持久化成入庫(kù),等流程不再阻塞的時(shí)候把協(xié)程重新從數(shù)據(jù)庫(kù)里拉起來(lái)繼續(xù)執(zhí)行。 常規(guī)版本的Python的generator是不可以被持久化保存的。但是stackless和pypy這兩個(gè)修改版本的Python解釋器可以。下面這段代碼演示了如何把一個(gè)執(zhí)行中的函數(shù)持久化保存,然后過(guò)段時(shí)間再把函數(shù)從上次執(zhí)行到的地方原樣拉起...
閱讀 1036·2022-07-19 10:19
閱讀 1806·2021-09-02 15:15
閱讀 1023·2019-08-30 15:53
閱讀 2668·2019-08-30 13:45
閱讀 2664·2019-08-26 13:57
閱讀 1998·2019-08-26 12:13
閱讀 1016·2019-08-26 10:55
閱讀 558·2019-08-26 10:46