日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python中协程实现的本质以及两个封装协程模块greenle、gevent

發(fā)布時間:2025/3/20 python 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python中协程实现的本质以及两个封装协程模块greenle、gevent 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

協(xié)程

協(xié)程,又稱微線程,纖程。英文名Coroutine。

協(xié)程是啥

協(xié)程是python個中另外一種實(shí)現(xiàn)多任務(wù)的方式,只不過比線程更小占用更小執(zhí)行單元(理解為需要的資源)。 為啥說它是一個執(zhí)行單元,因?yàn)樗詭PU上下文。這樣只要在合適的時機(jī), 我們可以把一個協(xié)程 切換到另一個協(xié)程。 只要這個過程中保存或恢復(fù) CPU上下文那么程序還是可以運(yùn)行的。

通俗的理解:在一個線程中的某個函數(shù),可以在任何地方保存當(dāng)前函數(shù)的一些臨時變量等信息,然后切換到另外一個函數(shù)中執(zhí)行,注意不是通過調(diào)用函數(shù)的方式做到的,并且切換的次數(shù)以及什么時候再切換到原來的函數(shù)都由開發(fā)者自己確定

協(xié)程和線程差異

在實(shí)現(xiàn)多任務(wù)時, 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡單。 操作系統(tǒng)為了程序運(yùn)行的高效性每個線程都有自己緩存Cache等等數(shù)據(jù),操作系統(tǒng)還會幫你做這些數(shù)據(jù)的恢復(fù)操作。 所以線程的切換非常耗性能。但是協(xié)程的切換只是單純的操作CPU的上下文,所以一秒鐘切換個上百萬次系統(tǒng)都抗的住。

簡單實(shí)現(xiàn)協(xié)程

利用yield關(guān)鍵字(其實(shí)質(zhì)就是一個生成器,有關(guān)于生成器的詳細(xì)解析:python生成器詳解)

import time ? def test1():while True:print("----test1---")yieldtime.sleep(0.5) ? def test2():while True:print("----test2---")yieldtime.sleep(0.5) ? def main():t1 = test1()t2 = test2()while True:next(t1)next(t2) ? if __name__ == "__main__":main()

?

運(yùn)行結(jié)果:

----test1--- ----test2--- ----test1--- ----test2--- ----test1--- ----test2--- ----test1--- ----test2--- ----test1--- ----test2--- ----test1--- ----test2--- ...省略...

?

greenlet

為了更好使用協(xié)程來完成多任務(wù),python中的greenlet模塊對其封裝,從而使得切換任務(wù)變的更加簡單

安裝方式

使用如下命令安裝greenlet模塊:

sudo pip3 install greenlet#coding=utf-8 ? from greenlet import greenlet import time ? def test1():while True:print "---A--"gr2.switch()time.sleep(0.5) ? def test2():while True:print "---B--"gr1.switch()time.sleep(0.5) ? gr1 = greenlet(test1) gr2 = greenlet(test2) ? #切換到gr1中運(yùn)行 gr1.switch()

?

運(yùn)行效果

---A-- ---B-- ---A-- ---B-- ---A-- ---B-- ---A-- ---B-- ...省略...

?

gevent

greenlet已經(jīng)實(shí)現(xiàn)了協(xié)程,但是這個還的人工切換,是不是覺得太麻煩了,不要捉急,python還有一個比greenlet更強(qiáng)大的并且能夠自動切換任務(wù)的模塊gevent

其原理是當(dāng)一個greenlet遇到IO(指的是input output 輸入輸出,比如網(wǎng)絡(luò)、文件操作等)操作時,比如訪問網(wǎng)絡(luò),就自動切換到其他的greenlet,等到IO操作完成,再在適當(dāng)?shù)臅r候切換回來繼續(xù)執(zhí)行。

由于IO操作非常耗時,經(jīng)常使程序處于等待狀態(tài),有了gevent為我們自動切換協(xié)程,就保證總有g(shù)reenlet在運(yùn)行,而不是等待IO

安裝

pip3 install gevent

?

1. gevent的使用

import gevent ? def f(n):for i in range(n):print(gevent.getcurrent(), i) ? g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

?

運(yùn)行結(jié)果

<Greenlet at 0x10e49f550: f(5)> 0 <Greenlet at 0x10e49f550: f(5)> 1 <Greenlet at 0x10e49f550: f(5)> 2 <Greenlet at 0x10e49f550: f(5)> 3 <Greenlet at 0x10e49f550: f(5)> 4 <Greenlet at 0x10e49f910: f(5)> 0 <Greenlet at 0x10e49f910: f(5)> 1 <Greenlet at 0x10e49f910: f(5)> 2 <Greenlet at 0x10e49f910: f(5)> 3 <Greenlet at 0x10e49f910: f(5)> 4 <Greenlet at 0x10e49f4b0: f(5)> 0 <Greenlet at 0x10e49f4b0: f(5)> 1 <Greenlet at 0x10e49f4b0: f(5)> 2 <Greenlet at 0x10e49f4b0: f(5)> 3 <Greenlet at 0x10e49f4b0: f(5)> 4

?

可以看到,3個greenlet是依次運(yùn)行而不是交替運(yùn)行

2. gevent切換執(zhí)行

import gevent ? def f(n):for i in range(n):print(gevent.getcurrent(), i)#用來模擬一個耗時操作,注意不是time模塊中的sleepgevent.sleep(1) ? g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

?

運(yùn)行結(jié)果

<Greenlet at 0x7fa70ffa1c30: f(5)> 0 <Greenlet at 0x7fa70ffa1870: f(5)> 0 <Greenlet at 0x7fa70ffa1eb0: f(5)> 0 <Greenlet at 0x7fa70ffa1c30: f(5)> 1 <Greenlet at 0x7fa70ffa1870: f(5)> 1 <Greenlet at 0x7fa70ffa1eb0: f(5)> 1 <Greenlet at 0x7fa70ffa1c30: f(5)> 2 <Greenlet at 0x7fa70ffa1870: f(5)> 2 <Greenlet at 0x7fa70ffa1eb0: f(5)> 2 <Greenlet at 0x7fa70ffa1c30: f(5)> 3 <Greenlet at 0x7fa70ffa1870: f(5)> 3 <Greenlet at 0x7fa70ffa1eb0: f(5)> 3 <Greenlet at 0x7fa70ffa1c30: f(5)> 4 <Greenlet at 0x7fa70ffa1870: f(5)> 4 <Greenlet at 0x7fa70ffa1eb0: f(5)> 4

?

3. 給程序打補(bǔ)丁

from gevent import monkey import gevent import random import time ? def coroutine_work(coroutine_name):for i in range(10):print(coroutine_name, i)time.sleep(random.random()) ? gevent.joinall([gevent.spawn(coroutine_work, "work1"),gevent.spawn(coroutine_work, "work2") ])

?

運(yùn)行結(jié)果

work1 0 work1 1 work1 2 work1 3 work1 4 work1 5 work1 6 work1 7 work1 8 work1 9 work2 0 work2 1 work2 2 work2 3 work2 4 work2 5 work2 6 work2 7 work2 8 work2 9

?

? from gevent import monkey import gevent import random import time ? # 有耗時操作時需要 monkey.patch_all() # 將程序中用到的耗時操作的代碼,換為gevent中自己實(shí)現(xiàn)的模塊 ? def coroutine_work(coroutine_name):for i in range(10):print(coroutine_name, i)time.sleep(random.random()) ? gevent.joinall([gevent.spawn(coroutine_work, "work1"),gevent.spawn(coroutine_work, "work2") ])

?

?

運(yùn)行結(jié)果

work1 0 work2 0 work1 1 work1 2 work1 3 work2 1 work1 4 work2 2 work1 5 work2 3 work1 6 work1 7 work1 8 work2 4 work2 5 work1 9 work2 6 work2 7 work2 8 work2 9

?

轉(zhuǎn)載于:https://www.cnblogs.com/wangcoo/p/10018460.html

總結(jié)

以上是生活随笔為你收集整理的python中协程实现的本质以及两个封装协程模块greenle、gevent的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。