Python經過yield
提供了對協程的基本支持,可是不徹底。而第三方的gevent爲Python提供了比較完善的協程支持。python
gevent是第三方庫,經過greenlet實現協程,其基本思想是:git
當一個greenlet遇到IO操做時,好比訪問網絡,就自動切換到其餘的greenlet,等到IO操做完成,再在適當的時候切換回來繼續執行。因爲IO操做很是耗時,常常使程序處於等待狀態,有了gevent爲咱們自動切換協程,就保證總有greenlet在運行,而不是等待IO。github
因爲切換是在IO操做時自動完成,因此gevent須要修改Python自帶的一些標準庫,這一過程在啓動時經過monkey patch完成:網絡
先了解greenlet,這個庫用來學習的 功能不是不少。ide
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 from greenlet import greenlet 6 7 8 def test1(): 9 print 12 10 #切換到g2 11 gr2.switch() 12 print 34 13 #切換到g2繼續執行上次的任務 14 gr2.switch() 15 16 17 def test2(): 18 print 56 19 gr1.switch() 20 print 78 21 22 gr1 = greenlet(test1) 23 gr2 = greenlet(test2) 24 gr1.switch()
結果:學習
12
56
34
78fetch
經過switc方法能夠控制 協程何時切換,協程會記錄上次執行的點而後導入這個點繼續執行url
gevent庫方法(基於greenlet來作的):spa
1 from gevent import monkey; monkey.patch_all() 2 import gevent 3 import urllib2 4 5 def f(url): 6 print('GET: %s' % url) 7 resp = urllib2.urlopen(url) 8 data = resp.read() 9 print('%d bytes received from %s.' % (len(data), url)) 10 11 #這裏就不想greenlet須要手動切換,這裏是自動切換 12 gevent.joinall([ 13 gevent.spawn(f, 'https://www.python.org/'), 14 gevent.spawn(f, 'https://www.yahoo.com/'), 15 gevent.spawn(f, 'https://github.com/'), 16 ])
openstack中用到的協程模塊eventlet3d
1 import eventlet 2 from eventlet.green import urllib2 3 4 5 urls = [ 6 "http://www.baidu.com", 7 "https://github.com/", 8 "http://www.qq.com", 9 ] 10 11 12 def fetch(url): 13 print(url) 14 return url,urllib2.urlopen(url).read() 15 16 17 pool = eventlet.GreenPool() 18 19 20 for url,body in pool.imap(fetch, urls): 21 print("go:%s === body-len:%d"%(url,len(body)))