参考资料:
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000
1、协程,又称微线程,纤程,英文名Coroutine。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。协程的执行有点像多线程,但协程的特点在于是一个线程执行,和多线程比,协程具有如下优势:
(1)最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
(2)第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
2、Python对协程的支持还非常有限,用在generator中的yield可以一定程度上实现协程。下面是我的学习代码:
import time
#子程序,负责输出变量n的当前值
def output():
r = ''
while True:
#通过yeild取得消息,并返回处理结果
n = yield r
if not n:
return
print 'output result:', n
time.sleep(1)
r = '200 OK'
#子程序,负责计算并调用子程序output完成输出
def calc(o):
#启动生成器
o.next()
n = 0
while n < 5:
n = n + 1
print 'calc result:', n
#调用output子程序
r = o.send(n)
print 'output return:', r
#结束调用
o.close()
#测试入口
def Test():
calc(output())
通过代码可以看到,calc和output两个子程序协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
3、Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。
gevent是第三方库,通过greenlet实现协程,其基本思想是:当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成。
当然,应用gevent前,依然需要pip install gevent命令进行安装。如下图所示:
下面是参考资料1中给出的示例代码:
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))
#测试入口
def Test():
gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://github.com/'),
])
今天就学习到这里,下一节将学习利用python进行WEB开发过程中的一些技巧。