Python 多工 協程

2021-10-02 11:25:30 字數 4111 閱讀 1896

高階程式設計技巧 學習筆記

1.1、同步 & 非同步

1.2、阻塞 & 非阻塞

2.1、什麼是協程?

協程,又稱微執行緒。協程是 python 個中另外一種實現多工的方式,只不過比執行緒更小占用更小執行單元(理解為需要的資源)。

2.2、python中的協程大概經歷了如下三個階段:

最初的生成器變形yield / send

yield from

在最近的 python3.5 版本中引入async / await關鍵字

3.1、使用 greenlet 完成多工

from greenlet import greenlet

import time

# 協程利用程式的 io 來切換任務

# 這裡簡單一點, 就用 sleep 延遲代替 io

defdemo1()

:for i in

range(5

):print

("demo1"

) time.sleep(

0.5)

defdemo2()

:for i in

range(5

):print

("demo2"

) time.sleep(

0.5)

gr1 = greenlet(demo1)

gr2 = greenlet(demo2)

gr1.switch(

)gr2.switch(

)

執行發現,程式先執行完第乙個任務再執行下乙個任務?說明在開始執行任務後並沒有切換任務。

修改任務,使其完成切換操作。

from greenlet import greenlet

import time

# 協程利用程式的 io 來切換任務

# 這裡簡單一點, 就用 sleep 延遲代替 io

defdemo1()

:for i in

range(5

):print

("demo1"

)# 執行 "任務2", (相當於從任務1切換到任務2)

gr2.switch(

) time.sleep(

0.5)

defdemo2()

:for i in

range(5

):print

("demo2"

)# 執行 "任務1"

gr1.switch(

) time.sleep(

0.5)

gr1 = greenlet(demo1)

gr2 = greenlet(demo2)

# 執行 "任務1"

gr1.switch(

)

存在問題,每次執任務時都要新增切換任務的語句,這麼做不緊麻煩而且還固定了每個任務的執行順序。

使用 gevent 可以更好的解決這個問題。

3.2、使用 gevent 完成多工

import gevent

import time

deff1

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

deff2

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

deff3

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

g1 = gevent.spawn(f1,5)

g2 = gevent.spawn(f2,5)

g3 = gevent.spawn(f3,5)

g1.join(

)g2.join(

)g3.join(

)

嗯?這列印的結果不還是一樣嗎?

其實是因為gevent並不認識time.sleep()。要想再使用gevent的時候,實現延遲,需要使用gevent.sleep()

import gevent

import time

deff1

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

gevent.sleep(

0.5)

deff2

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

gevent.sleep(

0.5)

deff3

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

gevent.sleep(

0.5)

g1 = gevent.spawn(f1,5)

g2 = gevent.spawn(f2,5)

g3 = gevent.spawn(f3,5)

g1.join(

)g2.join(

)g3.join(

)

gevent.sleep()替換time.sleep()確實可以解決問題,但是如果專案中需要修改的地方有很多,那手動去乙個乙個修改顯然是不可取的。此時,就要用到monkey.patch_all()了。

import gevent

import time

from gevent import monkey

# 將程式中用到的耗時操作, 都換為 gevent 中實現的模組

# 相當於打了乙個補丁

monkey.patch_all(

)def

f1(n)

:for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

deff2

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

deff3

(n):

for i in

range

(n):

print

(gevent.getcurrent(

), i)

time.sleep(

0.5)

g1 = gevent.spawn(f1,5)

g2 = gevent.spawn(f2,5)

g3 = gevent.spawn(f3,5)

g1.join(

)g2.join(

)g3.join(

)

多工 協程

示例 import time defwork1 while true print 正在掃地 yield defwork2 while true print 正在搬磚 yield w1 work1 w2 work2 協程肯定是併發執行 while true next w1 next w2 greenl...

Python 多工之協程(3)實現多工

學習理解迭代器和生成器之後,開始使用協程來實現多工 當乙個函式中包含yield關鍵字,那麼這個函式就不再是乙個普通的函式,它的返回值是乙個生成器物件。我們可以使用next 或send 函式來啟動喚醒生成器物件,當程式第一次執行到yield時,程式暫停執行,並返回yield後邊跟的變數,當再次喚醒時,...

多工18 協程

協程,又稱微執行緒,纖程。英文名coroutine。協程是python個中另外一種實現多工的方式,只不過比執行緒更小占用更小執行單元 理解為需要的資源 為啥說它是乙個執行單元,因為它自帶cpu上下文。這樣只要在合適的時機,我們可以把乙個協程 切換到另乙個協程。只要這個過程中儲存或恢復 cpu上下文那...