学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)
生活随笔
收集整理的這篇文章主要介紹了
学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
立即學習:https://edu.csdn.net/course/play/24458/296457?utm_source=blogtoedu
協程(yield,greenlet,gevent)
?
1.協程:在單線程中通過不斷地在多個任務之間進行切換執行,來達到并發的效果的線程,可以提高效率
?
2.yield實現協程
#yield = return + generator(生成器) #有yield的函數就是生成器,不會直接執行函數,首先獲得生成器對象然后使用next函數這才開始運行函數 #next方法#并發執行 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實現協程
#greenlet也是i一個可以實現單線程內并發的效果,但是和yield一樣不能檢測i/o模型 #切換的格式為: ''' g1 = greenlet(function1)#獲得對象 g2.switch(para)#從當前任務切換到g2對應的任務中 ''' #協程并發 from greenlet import greenlet#定義函數一 def eat(name):print('%s1 is eating'%name)g2.switch('同學')print('%s2 is eating'%name)g2.switch()#定義函數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('同學')?
4.gevent實現協程
#1.gevent模塊是基于greenlet模塊的,具有檢測自身I/O操作的功能 import gevent,time#定義任務1 def eat(name):print('%s eat 1'%name)#自身的I/O操作。可以被檢測出,一旦檢測出就自動進行任務·切換gevent.sleep(3)print('%s eat 2'%name)#定義任務2 def play(name):print('%s play 1'%name)gevent.sleep(4)print('%s play 2'%name)start_time = time.time() #創建gevent對象,只是提交了任務,要想出結果,必須跟join函數配對使用 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.0197389125823975#運行時間接近4秒,即兩個任務并發執行的#首先該程序是單線程,只有一個主線程,但是含有兩個任務,首先按照代碼從上到下執行, 執行到創建對象時,會自動跳轉到對應的函數中去,如g1跳到eat函數,執行第一次打印, 檢測到自身gevent.sleep()I/O操作后,就自動切換到下一個任務,執行play函數的第一次 打印,后面就是兩個任務均處于等待狀態,期間一直在兩個任務之間切換進行檢測,因為eat時間短, 所以先執行eat函數的第二次打印任務,接著就是Play的第二次打印#因此這里實現了單線程兩個任務并發的效果 '''#2.gevent模塊是基于greenlet模塊的,具有檢測自身I/O操作的功能,不能檢測自身以外的I/O操作,如time.sleep() import gevent,time#定義任務1 def eat(name):print('%s eat 1'%name)#自身的I/O操作。可以被檢測出,一旦檢測出就自動進行任務·切換time.sleep(3)print('%s eat 2'%name)#定義任務2 def play(name):print('%s play 1'%name)time.sleep(4)print('%s play 2'%name)start_time = time.time() #創建gevent對象,只是異步提交了任務,不會等結果的出來,要想出結果,必須跟join函數或者和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 #運行時間接近與兩個任務I/O操作的時間總和,因此gevent不能檢測出自身以為的I/O操作 '''#3.gevent.monkey.patch_all():可以檢測到自身以外的I/O操作 import gevent,time from gevent import monkey monkey.patch_all()#定義任務1 def eat(name):print('%s eat 1'%name)#自身的I/O操作。可以被檢測出,一旦檢測出就自動進行任務·切換time.sleep(3)print('%s eat 2'%name)#定義任務2 def play(name):print('%s play 1'%name)time.sleep(4)print('%s play 2'%name)start_time = time.time() #創建gevent對象,只是提交了任務,要想出結果,必須跟join函數配對使用 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操作,自動進行切換,實現了單線程并發的效果 '''?
總結
以上是生活随笔為你收集整理的学习笔记(35):Python网络编程并发编程-协程(yield,greenlet,gevent模块)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pythonista安卓_Android
- 下一篇: 学习笔记(35续):Python网络编程