Python学习笔记(二十七)协程

参考资料:

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开发过程中的一些技巧。
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页