学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)
生活随笔
收集整理的這篇文章主要介紹了
学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
立即學(xué)習(xí):https://edu.csdn.net/course/play/24458/296457?utm_source=blogtoedu
協(xié)程(yield,greenlet,gevent)
?
1.協(xié)程:在單線程中通過不斷地在多個任務(wù)之間進行切換執(zhí)行,來達到并發(fā)的效果的線程,可以提高效率
?
2.yield實現(xiàn)協(xié)程
#yield = return + generator(生成器) #有yield的函數(shù)就是生成器,不會直接執(zhí)行函數(shù),首先獲得生成器對象然后使用next函數(shù)這才開始運行函數(shù) #next方法#并發(fā)執(zhí)行 import time def productor():g = costumor()for i in range(100):res = next(g)print(res)def costumor():for i in range(100):res = yield "*"*5+"%s"%i+'*'*5if __name__ == '__main__':start_time = time.time()productor()end_time = time.time()print('%.9f'%float(end_time-start_time))#串行 def productor():res = costumor()for i in res:print('*'*5+str(i)+"*"*5)def costumor():res=[]for i in range(100):res.append(i)return resif __name__ == '__main__':start_time = time.time()productor()end_time = time.time()print('%.9f'%float(end_time-start_time))?
3.greenlet實現(xiàn)協(xié)程
#greenlet也是i一個可以實現(xiàn)單線程內(nèi)并發(fā)的效果,但是和yield一樣不能檢測i/o模型 #切換的格式為: ''' g1 = greenlet(function1)#獲得對象 g2.switch(para)#從當(dāng)前任務(wù)切換到g2對應(yīng)的任務(wù)中 ''' #協(xié)程并發(fā) from greenlet import greenlet#定義函數(shù)一 def eat(name):print('%s1 is eating'%name)g2.switch('同學(xué)')print('%s2 is eating'%name)g2.switch()#定義函數(shù)2 def play(name):print('%s1 is playing'%name)g1.switch()print('%s2 is playing'%name)if __name__ == '__main__':g1 = greenlet(eat)g2 = greenlet(play)g1.switch('同學(xué)')?
4.gevent實現(xiàn)協(xié)程
#1.gevent模塊是基于greenlet模塊的,具有檢測自身I/O操作的功能 import gevent,time#定義任務(wù)1 def eat(name):print('%s eat 1'%name)#自身的I/O操作。可以被檢測出,一旦檢測出就自動進行任務(wù)·切換gevent.sleep(3)print('%s eat 2'%name)#定義任務(wù)2 def play(name):print('%s play 1'%name)gevent.sleep(4)print('%s play 2'%name)start_time = time.time() #創(chuàng)建gevent對象,只是提交了任務(wù),要想出結(jié)果,必須跟join函數(shù)配對使用 g1 = gevent.spawn(eat,'john') g2 = gevent.spawn(play,'lucy')g1.join() g2.join() end_time = time.time() print(end_time-start_time) ''' 運行結(jié)果: john eat 1 lucy play 1 john eat 2 lucy play 2 4.0197389125823975#運行時間接近4秒,即兩個任務(wù)并發(fā)執(zhí)行的#首先該程序是單線程,只有一個主線程,但是含有兩個任務(wù),首先按照代碼從上到下執(zhí)行, 執(zhí)行到創(chuàng)建對象時,會自動跳轉(zhuǎn)到對應(yīng)的函數(shù)中去,如g1跳到eat函數(shù),執(zhí)行第一次打印, 檢測到自身gevent.sleep()I/O操作后,就自動切換到下一個任務(wù),執(zhí)行play函數(shù)的第一次 打印,后面就是兩個任務(wù)均處于等待狀態(tài),期間一直在兩個任務(wù)之間切換進行檢測,因為eat時間短, 所以先執(zhí)行eat函數(shù)的第二次打印任務(wù),接著就是Play的第二次打印#因此這里實現(xiàn)了單線程兩個任務(wù)并發(fā)的效果 '''#2.gevent模塊是基于greenlet模塊的,具有檢測自身I/O操作的功能,不能檢測自身以外的I/O操作,如time.sleep() import gevent,time#定義任務(wù)1 def eat(name):print('%s eat 1'%name)#自身的I/O操作??梢员粰z測出,一旦檢測出就自動進行任務(wù)·切換time.sleep(3)print('%s eat 2'%name)#定義任務(wù)2 def play(name):print('%s play 1'%name)time.sleep(4)print('%s play 2'%name)start_time = time.time() #創(chuàng)建gevent對象,只是異步提交了任務(wù),不會等結(jié)果的出來,要想出結(jié)果,必須跟join函數(shù)或者和joinall()配對使用, g1 = gevent.spawn(eat,'john') g2 = gevent.spawn(play,'lucy')g1.join() g2.join() #gevent.joinall([g1,g2]) end_time = time.time() print(end_time-start_time) ''' john eat 1 john eat 2 lucy play 1 lucy play 2 7.019653797149658 #運行時間接近與兩個任務(wù)I/O操作的時間總和,因此gevent不能檢測出自身以為的I/O操作 '''#3.gevent.monkey.patch_all():可以檢測到自身以外的I/O操作 import gevent,time from gevent import monkey monkey.patch_all()#定義任務(wù)1 def eat(name):print('%s eat 1'%name)#自身的I/O操作??梢员粰z測出,一旦檢測出就自動進行任務(wù)·切換time.sleep(3)print('%s eat 2'%name)#定義任務(wù)2 def play(name):print('%s play 1'%name)time.sleep(4)print('%s play 2'%name)start_time = time.time() #創(chuàng)建gevent對象,只是提交了任務(wù),要想出結(jié)果,必須跟join函數(shù)配對使用 g1 = gevent.spawn(eat,'john') g2 = gevent.spawn(play,'lucy')g1.join() g2.join() end_time = time.time() print(end_time-start_time) ''' john eat 1 lucy play 1 john eat 2 lucy play 2 4.009758949279785#說明檢測到了time.sleep()的I/O操作,自動進行切換,實現(xiàn)了單線程并發(fā)的效果 '''?
總結(jié)
以上是生活随笔為你收集整理的学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pythonista安卓_Android
- 下一篇: 机器学习项目笔记