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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

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

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

協程

協程,又稱微線程,纖程。英文名Coroutine。

協程是啥

協程是python個中另外一種實現多任務的方式,只不過比線程更小占用更小執行單元(理解為需要的資源)。 為啥說它是一個執行單元,因為它自帶CPU上下文。這樣只要在合適的時機, 我們可以把一個協程 切換到另一個協程。 只要這個過程中保存或恢復 CPU上下文那么程序還是可以運行的。

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

協程和線程差異

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

簡單實現協程

利用yield關鍵字(其實質就是一個生成器,有關于生成器的詳細解析: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()

?

運行結果:

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

?

greenlet

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

安裝方式

使用如下命令安裝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中運行 gr1.switch()

?

運行效果

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

?

gevent

greenlet已經實現了協程,但是這個還的人工切換,是不是覺得太麻煩了,不要捉急,python還有一個比greenlet更強大的并且能夠自動切換任務的模塊gevent

其原理是當一個greenlet遇到IO(指的是input output 輸入輸出,比如網絡、文件操作等)操作時,比如訪問網絡,就自動切換到其他的greenlet,等到IO操作完成,再在適當的時候切換回來繼續執行。

由于IO操作非常耗時,經常使程序處于等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在運行,而不是等待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()

?

運行結果

<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是依次運行而不是交替運行

2. gevent切換執行

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()

?

運行結果

<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. 給程序打補丁

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") ])

?

運行結果

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中自己實現的模塊 ? 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") ])

?

?

運行結果

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

?

轉載于:https://www.cnblogs.com/wangcoo/p/10018460.html

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。