>>> def mygenerator(): ... print 'start...' ... yield 5 ... >>> mygenerator() //在此處調(diào)用,并沒(méi)有打印出start...說(shuō)明存在yield的函數(shù)沒(méi)有被運(yùn)行,即暫停>>> mygenerator().next() //調(diào)用next()即可讓函數(shù)運(yùn)行. start... 5 >>>
如一個(gè)函數(shù)中出現(xiàn)多個(gè)yield則next()會(huì)停止在下一個(gè)yield前,見(jiàn)例2:
例2:
>>> def mygenerator(): ... print 'start...' ... yield 5 ... >>> mygenerator() //在此處調(diào)用,并沒(méi)有打印出start...說(shuō)明存在yield的函數(shù)沒(méi)有被運(yùn)行,即暫停>>> mygenerator().next() //調(diào)用next()即可讓函數(shù)運(yùn)行. start... 5 >>>
為什么yield 5會(huì)輸出5,yield 23會(huì)輸出23?
我們猜測(cè)可能是因?yàn)閥ield是表達(dá)式,存在返回值.
那么這是否可以認(rèn)為yield 5的返回值一定是5嗎?實(shí)際上并不是這樣,這個(gè)與send函數(shù)存在一定的關(guān)系,這個(gè)函數(shù)實(shí)質(zhì)上與next()是相似的,區(qū)別是send是傳遞yield表達(dá)式的值進(jìn)去,而next不能傳遞特定的值,只能傳遞None進(jìn)去,因此可以認(rèn)為g.next()和g.send(None)是相同的。見(jiàn)例3:
例3:
>>> def fun(): ... print 'start...' ... m = yield 5 ... print m ... print 'middle...' ... d = yield 12 ... print d ... print 'end...' ... >>> m = fun() //創(chuàng)建一個(gè)對(duì)象 >>> m.next() //會(huì)使函數(shù)執(zhí)行到下一個(gè)yield前 start... 5 >>> m.send('message') //利用send()傳遞值 message //send()傳遞進(jìn)來(lái)的 middle... 12 >>> m.next() None //可見(jiàn)next()返回值為空 end... Traceback (most recent call last): File "", line 1, in StopIteration
在multiprocess中的使用
python在處理數(shù)據(jù)的時(shí)候,memory-heavy 的數(shù)據(jù)往往會(huì)導(dǎo)致程序沒(méi)辦反運(yùn)行或者運(yùn)行期間服務(wù)器其他程序效率受到影響。這種情況往往會(huì)把數(shù)據(jù)集合變?yōu)橥ㄟ^(guò)genertor來(lái)遍歷。
但同時(shí)如我們所知,generoter看似只能被單進(jìn)程消費(fèi),這樣效率很低。
generator 可以被pool.map消費(fèi)。
看一下pool.py的源碼。
for i, task in enumerate(taskseq): ... try: put(task) except IOError: debug('could not put task on queue') break
實(shí)際是先將generator全部消費(fèi)掉放到queue中。然后通過(guò)map來(lái)并行。這樣是解決了使用map來(lái)并行。
但是依然沒(méi)有解決占用內(nèi)存的問(wèn)題。這里有兩步占用內(nèi)存。
解決第一個(gè)問(wèn)題,通過(guò)部分消費(fèi)generator來(lái)達(dá)到。
解決第二個(gè)問(wèn)題,可以通過(guò)imap來(lái)達(dá)到.
示例代碼如下:
import multiprocessing as mp import itertools import time def g(): for el in xrange(50): print el yield el import os def f(x): time.sleep(1) print str(os.getpid()) +" "+ str(x) return x * x if __name__ == '__main__': pool = mp.Pool(processes=4) # start 4 worker processes go = g() result = [] N = 11 while True: g2 = pool.imap(f, itertools.islice(go, N)) if g2: for i in g2: result.append(i) time.sleep(1) else: break print(result)
ps: 使用注意事項(xiàng)。在produce數(shù)據(jù)的時(shí)候,盡量少做操作,應(yīng)為即使是map也是單線程的來(lái)消費(fèi)數(shù)據(jù)。所以盡量把操作放到map中作。這樣才能更好的利用多進(jìn)程提高效率。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com