上一篇文章為:→3.4.8協(xié)程-greenlet版
gevent
greenlet已經(jīng)實(shí)現(xiàn)了協(xié)程鞭盟,但是這個(gè)還的人工切換圾结,是不是覺得太麻煩了,不要捉急齿诉,python還有一個(gè)比greenlet更強(qiáng)大的并且能夠自動(dòng)切換任務(wù)的模塊gevent
其原理是當(dāng)一個(gè)greenlet遇到IO(指的是input output 輸入輸出筝野,比如網(wǎng)絡(luò)、文件操作等)操作時(shí)粤剧,比如訪問網(wǎng)絡(luò)歇竟,就自動(dòng)切換到其他的greenlet,等到IO操作完成抵恋,再在適當(dāng)?shù)臅r(shí)候切換回來繼續(xù)執(zhí)行焕议。
由于IO操作非常耗時(shí),經(jīng)常使程序處于等待狀態(tài)弧关,有了gevent為我們自動(dòng)切換協(xié)程盅安,就保證總有g(shù)reenlet在運(yùn)行,而不是等待IO
1. gevent的使用
#coding=utf-8
#請(qǐng)使用python 2 來執(zhí)行此程序
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()
運(yùn)行結(jié)果
<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個(gè)greenlet是依次運(yùn)行而不是交替運(yùn)行
2. gevent切換執(zhí)行
import gevent
def f(n):
for i in range(n):
print gevent.getcurrent(), i
#用來模擬一個(gè)耗時(shí)操作别瞭,注意不是time模塊中的sleep
gevent.sleep(1)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()
運(yùn)行結(jié)果
<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個(gè)greenlet交替運(yùn)行
3. gevent并發(fā)下載器
當(dāng)然,實(shí)際代碼里株憾,我們不會(huì)用gevent.sleep()去切換協(xié)程蝙寨,而是在執(zhí)行到IO操作時(shí),gevent自動(dòng)切換嗤瞎,代碼如下
#coding=utf-8
from gevent import monkey;
import gevent
import urllib2
#有IO才做時(shí)需要這一句
monkey.patch_all()
def myDownLoad(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(myDownLoad, 'http://www.baidu.com/'),
gevent.spawn(myDownLoad, 'http://www.itcast.cn/'),
gevent.spawn(myDownLoad, 'http://www.itheima.com/'),
])
運(yùn)行結(jié)果
GET: http://www.baidu.com/
GET: http://www.itcast.cn/
GET: http://www.itheima.com/
102247 bytes received from http://www.baidu.com/.
166903 bytes received from http://www.itheima.com/.
162294 bytes received from http://www.itcast.cn/.
從上能夠看到是先發(fā)送的獲取baidu的相關(guān)信息墙歪,然后依次是itcast、itheima贝奇,但是收到數(shù)據(jù)的先后順序不一定與發(fā)送順序相同虹菲,這也就體現(xiàn)出了異步,即不確定什么時(shí)候會(huì)收到數(shù)據(jù)弃秆,順序不一定