非同步I O 協程

2021-10-02 21:59:20 字數 2901 閱讀 5273

什麼是協程呢?

協程(coroutines)是一種比執行緒更加輕量級的存在,正如乙個程序可以擁有多個執行緒一樣,乙個執行緒可以擁有多個協程。

協程不是被作業系統核心所管理的,而是完全由程式所控制,也就是在使用者態執行。這樣帶來的好處是效能大幅度的提公升,因為不會像執行緒切換那樣消耗資源。

協程不是程序也不是執行緒,而是乙個特殊的函式,這個函式可以在某個地方掛起,並且可以重新在掛起處外繼續執行。所以說,協程與程序、執行緒相比並不是乙個維度的概念。

python對協程的支援是通過generator實現的。

在generator中,我們不但可以通過for迴圈來迭代,還可以不斷呼叫next()函式獲取由yield語句返回的下乙個值。

但是python的yield不但可以返回乙個值,它還可以接收呼叫者發出的引數。

def

consumer()

: r =

''while

true

: n =

yield r

ifnot n:

return

print

('[consumer] consuming %s...'

% n)

r ='200 ok'

defproduce

(c):

c.send(

none

) n =

0while n <5:

n = n +

1print

('[producer] producing %s...'

% n)

r = c.send(n)

print

('[producer] consumer return: %s'

% r)

c.close(

)c = consumer(

)produce(c)

執行結果

[producer] producing 1..

.[consumer] consuming 1..

.[producer] consumer return

:200 ok

[producer] producing 2..

.[consumer] consuming 2..

.[producer] consumer return

:200 ok

[producer] producing 3..

.[consumer] consuming 3..

.[producer] consumer return

:200 ok

[producer] producing 4..

.[consumer] consuming 4..

.[producer] consumer return

:200 ok

[producer] producing 5..

.[consumer] consuming 5..

.[producer] consumer return

:200 ok

要理解上述例子,需要理解以下幾點:

1、例子中的c.send(none),其功能類似於next( c ),比如:

>>

>

defnum()

:yield

1yield

2>>

> c = num(

)>>

> c.send(

none)1

>>

> c.send(

none)2

>>

> c.send(

none

)traceback (most recent call last)

: file ""

, line 1,in

c.send(

none

)stopiteration

>>

>

2、n = yield r,這裡是一條語句,但要理解兩個知識點,賦值語句先計算= 右邊,由於右邊是 yield 語句,所以yield語句執行完以後,進入暫停,而賦值語句在下一次啟動生成器的時候首先被執行;

3、send 在接受none引數的情況下,等同於next(generator)的功能,但send同時也可接收其他引數,比如例子中的c.send(n)

>>

>

defnum()

: a =

yield

1while

true

: a =

yield a

>>

> c = num(

)>>

> c.send(

none)1

>>

> c.send(5)

5>>

> c.send(

100)

100

在上面的例子中,首先使用 c.send(none),返回生成器的第乙個值,a = yield 1 ,也就是1(但此時,並未執行賦值語句)。

接著我們使用了c.send(5),再次啟動生成器,並同時傳入了乙個引數5,再次啟動生成的時候,從上次yield語句斷掉的地方開始執行,即 a 的賦值語句,由於我們傳入了乙個引數5,所以a被賦值為5,接著程式進入whlie迴圈,當程式執行到 a = yield a,同理,先返回生成器的值 5,下次啟動生成器的時候,再執行賦值語句,以此類推…

所以c.send(n)的用法就是" python的yield不但可以返回乙個值,它還可以接收呼叫者發出的引數。"

但注意,在乙個生成器函式未啟動之前,是不能傳遞值進去。也就是說在使用c.send(n)之前,必須先使用c.send(none)或者next( c )來返回生成器的第乙個值。

非同步IO 協程回顧yield from

咱先看看yield和yield form 的區別在哪兒,如下,全部傳入range 10 def g1 iterable yield iterable def g2 iterable yield from iterable for value in g1 range 10 print value fo...

python協程與非同步協程

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

Python Demo18 非同步IO之協程

協程是通過generator來實現的,就是yield關鍵字和send 函式的使用。yield關鍵字可以將值 資訊 返回,同時在資訊返回後使程式停留在當前行。def test number 1.while true number 2.yield number print yield下面的 t test...