Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。
gevent是第三方库,通过greenlet实现协程,其基本思想是:
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:
先了解greenlet,这个库用来学习的 功能不是很多。

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
78
通过switc方法可以控制 协程什么时候切换,协程会记录上次执行的点然后导入这个点继续执行
gevent库方法(基于greenlet来做的):

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中用到的协程模块eventlet

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)))
来源:https://www.cnblogs.com/menkeyi/p/7145464.html
