玩轉python(6)協程

2022-09-13 11:45:10 字數 1223 閱讀 1336

多工系統一般都需要解決乙個問題:多個任務如何排程。搶占式排程就是一種很常見的任務排程機制。以單核模式下的程序排程為例,乙個程序處於執行狀態,其他的處於就緒佇列,等到當前執行的程序放棄cpu的使用權,系統將cpu立刻分配給新到達的程序,由於任務的執行順序是不確定的,看上去就像一堆任務在競爭cpu的使用權,所以這種多工執行方式叫做「多工競爭」。與之對應的是非搶占式排程。當前任務會持續執行下去直到因為某些原因主動放棄cpu的使用權,各個任務的執行順序是確定的,就像在互相協作,所以這種多工執行方式也叫做「多工協作」。協程就是一種典型的多工協作解決方案。協程是指乙個過程,這個過程與呼叫方協作,產出由呼叫方提供的值。它的執行流程大致如下:

協程a開始執行。

協程a執行到某一步,暫停執行,執行權轉移到協程b。

協程b執行一段時間後交還執行權。

協程a恢復執行。

那麼生成器是如何與協程扯上關係的呢?在乙個生成器中,yield item這行**會產出乙個值,提供給next()的呼叫方;此外,還會作出讓步,暫停執行生成器,讓呼叫方繼續工作,直到需要使用另乙個值時再呼叫next()。呼叫方會從生成器中拉取值。如果只能產出值,生成器顯然用處不大。在python2.5之後的版本中,生成器api 中增加了send()方法。生成器的呼叫方可以使用send()方法傳送資料,傳送的資料會成為生成器函式中yield表示式的值。這樣生成器既能接收資料,又能產出資料,可以作為協程使用。下面是乙個簡單的協程例項:

def fun():

r = ''

while true:

n = yield r

if not n:

return

print('fun test %s...' % n)

r = '200 ok'

協程在執行到n = yield r這個表示式時,首先輸出r,然後將接收到的資料賦給n。然後向下執行直到遇到下乙個yield語句,迴圈往復。接下來我們來看看這個協程是怎麼工作的~

c = fun()

next(c)

c.send('1')

測試結果如下:

input:1
儘管fun()中有乙個死迴圈,但是遇到yield,協程就會讓出執行權。而且協程有個亮點,它沒有涉及到上下文切換,所有的過程都是在使用者空間進行的,協程的建立開銷也很小,所以完全沒有建立執行緒時的各種考慮。因此如果有多個任務,並且我們知道如何安排任務協作的情況下,協程無疑是乙個好選擇。

玩轉python(6)協程

多工系統一般都需要解決乙個問題 多個任務如何排程。搶占式排程就是一種很常見的任務排程機制。以單核模式下的程序排程為例,乙個程序處於執行狀態,其他的處於就緒佇列,等到當前執行的程序放棄cpu的使用權,系統將cpu立刻分配給新到達的程序,由於任務的執行順序是不確定的,看上去就像一堆任務在競爭cpu的使用...

python協程與非同步協程

在前面幾個部落格中我們一一對應解決了消費者消費的速度跟不上生產者,浪費我們大量的時間去等待的問題,在這裡,針對業務邏輯比較耗時間的問題,我們還有除了多程序之外更優的解決方式,那就是協程和非同步協程。在引入這個概念之前我們先看 看這個圖 從這個我們可以看出來,假如來了9個任務,即使我們開了多程序,在業...

python協程使用 協程的案例

概念 使用者層面在乙個執行緒中進行多工切換的機制,比執行緒更加輕量級 實現併發量更大 協程的使用 使用第三方庫 gevent gevent 是乙個基於協程的 python 網路庫,在遇到 io 阻塞時,程式會自動進行切換,可以讓我們用同步的放肆寫非同步 io 協程的使用 from gevent im...