参考资料:
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开发过程中的一些技巧。