20180309协程串讲

一、协程的诞生和定义

1.why

CPU密集型:多进程因为资源有限,创建销毁需要大量资源,所以需要多线程;

IO密集型:多线程因为有切换问题,所以异步编程;

异步编程因为事件调度、回调函数、代码编写不“直观”,所以有协程;

2.what

与子程序一样,协程也是一种程序组件。协程更适合于用来实现彼此熟悉的程序组件,如合作式多任务,迭代器,无限列表和管道。

3.协程的特点

多个协程在操作系统层面上是一个线程;协程之间自由切换;协程之间的调度需要用户编写。

例子:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def count(n):
    x = 0
    while x < n:
        yield x
        x += 1

def grep(pattern):
    print "looking for pattern %s" % pattern
    while True:
        line = (yield)
        if pattern in line:
            print line

if __name__ == '__main__':
    g = grep("python")
    g.next()
    print "after next"
    g.send("yeas")
    print "after yeas"
    g.send("python gene")
    print "after python gene"

执行结果:

[work@your_machine test]$ python corun.py  
 looking for pattern python  
 after next  
 after yeas  
 python gene  
 after python gene

特点:

带有关键字yield的函数,叫作生成器,用来生成序列。

对生成器对象调用next()方法,生成器执行至下一次yield再暂停。

Python2.5 PEP342特性:Send(XXX)

入口是yield,出口也是yield,yield放出时间片。

线程和协程的区别之一:多个入口多个出口;协程可以保存现场(比如count里面的x)

4.协程的优缺点

优点:多协程共享一个进程资源。协程间切换开销小;

缺点:实际上是单线程,CPU密集型的话会一直占用CPU;

协程标识:有生成器、允许接收数据;

二、协程实战

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time

def follow(file_name, target):
    file_name.seek(0, 2) # go to the end
    while True:
        line = file_name.readline()
        if not line:
            time.sleep(0.1)
            continue
        target.send(line)

def grep(pattern, target):
    while True:
        line = (yield)
        if pattern in line:
            target.send(line)

def printer():
    while True:
        line = (yield)
        print line

if __name__ == '__main__':
    f = open("myfile.log")
    # 对生成器对象调用next()方法,生成器执行至下一次yield再暂停。
    # python的yield第一次不能用send发送任务
    pt = printer()
    pt.next()
    gr = grep("python", pt)
    gr.next()
    follow(f, gr)

三、gevent

comments powered by Disqus