python之gevent模組實現協程

2022-06-25 15:24:09 字數 2001 閱讀 1114

python通過yield提供了對協程的基本支援,但是不完全。而第三方的gevent為python提供了比較完善的協程支援。

gevent是第三方庫,通過greenlet實現協程,其基本思想是:

當乙個greenlet遇到io操作時,比如訪問網路,就自動切換到其他的greenlet,等到io操作完成,再在適當的時候切換回來繼續執行。由於io操作非常耗時,經常使程式處於等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在執行,而不是等待io。

由於切換是在io操作時自動完成,所以gevent需要修改python自帶的一些標準庫,這一過程在啟動時通過monkey patch完成:

from gevent import monkey; monkey.patch_socket()

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

執行結果:

 0

1 2

3 4

0 1

2 3

4 0

1 2

3 4

可以看到,3個greenlet是依次執行而不是交替執行。

要讓greenlet交替執行,可以通過gevent.sleep()交出控制權:

def f(n):

for i in range(n):

print gevent.getcurrent(), i

gevent.sleep(0)

執行結果:

 0

0 0

1 1

1 2

2 2

3 3

3 4

4 4

3個greenlet交替執行,

把迴圈次數改為500000,讓它們的執行時間長一點,然後在作業系統的程序管理器中看,執行緒數只有1個。

當然,實際**裡,我們不會用gevent.sleep()去切換協程,而是在執行到io操作時,gevent自動切換,**如下:

from gevent import monkey; monkey.patch_all()

import gevent

import urllib2

def f(url):

print('get: %s' % url)

resp = urllib2.urlopen(url)

data = resp.read()

print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([

gevent.spawn(f, ''),

gevent.spawn(f, ''),

gevent.spawn(f, ''),

])

執行結果:

get: 

get:

get:

45661 bytes received from .

14823 bytes received from .

304034 bytes received from .

從結果看,3個網路操作是併發執行的,而且結束順序不同,但只有乙個執行緒。

使用gevent,可以獲得極高的併發效能,但gevent只能在unix/linux下執行,在windows下不保證正常安裝和執行。

python之gevent模組實現協程

python通過yield提供了對協程的基本支援,但是不完全。而第三方的gevent為python提供了比較完善的協程支援。gevent是第三方庫,通過greenlet實現協程,其基本思想是 當乙個greenlet遇到io操作時,比如訪問網路,就自動切換到其他的greenlet,等到io操作完成,再...

python 協程 gevent模組

import requests 匯入 gevent import gevent 由於切換是在io操作時自動完成 所以gevent需要修改python自帶的一些標準庫 這一過程在啟動時通過monkey patch 猴子補丁 完成 from gevent import monkey monkey.pat...

初識gevent模組

協程的本質是乙個執行緒執行多個任務,檢測到i o操作就切換任務執行,以實現更高效的利用cpu gevent可以實現任務間的切換 from gevent import monkey monkey.patch all import gevent import time gevent預設只識別自身模組中的...