日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

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

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

協(xié)程

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

協(xié)程是啥

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

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

協(xié)程和線程差異

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

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

利用yield關(guān)鍵字(其實(shí)質(zhì)就是一個(gè)生成器,有關(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模塊對(duì)其封裝,從而使得切換任務(wù)變的更加簡(jiǎn)單

安裝方式

使用如下命令安裝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é)程,但是這個(gè)還的人工切換,是不是覺得太麻煩了,不要捉急,python還有一個(gè)比greenlet更強(qiáng)大的并且能夠自動(dòng)切換任務(wù)的模塊gevent

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

由于IO操作非常耗時(shí),經(jīng)常使程序處于等待狀態(tài),有了gevent為我們自動(dòng)切換協(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個(gè)greenlet是依次運(yùn)行而不是交替運(yùn)行

2. gevent切換執(zhí)行

import gevent ? def f(n):for i in range(n):print(gevent.getcurrent(), i)#用來模擬一個(gè)耗時(shí)操作,注意不是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 ? # 有耗時(shí)操作時(shí)需要 monkey.patch_all() # 將程序中用到的耗時(shí)操作的代碼,換為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的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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