python--协程之特别篇

Python经过yield提供了对协程的基本支持,可是不彻底。而第三方的gevent为Python提供了比较完善的协程支持。

gevent是第三方库,经过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操做时,好比访问网络,就自动切换到其余的greenlet,等到IO操做完成,再在适当的时候切换回来继续执行。因为IO操做很是耗时,常常使程序处于等待状态,有了gevent为咱们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

因为切换是在IO操做时自动完成,因此gevent须要修改Python自带的一些标准库,这一过程在启动时经过monkey patch完成:


一、gevent协程适合I/O密集,不适合CPU密集。 
三、gevent协程没法发挥多核优点,事实上,协程只是以单线程的方式在运行。 
三、子程序就是协程的一种特例

从下面例子入道, 单线程 函数级 切换任务执行,支持大量并发, 而 线程 以及 进程都是内核级别的

# -*- coding: utf-8 -*-
__author__ = 'Frank Li'

import asyncio
from functools import wraps
import time

def time_count(func):
    @wraps(func)
    def inner_func(*args,**kw):
        start = time.time()
        result = func(*args,**kw)
        end = time.time()
        print('{} cost {:.1f} s totally'.format(func.__name__,(end-start)))
        return result
    return inner_func

@asyncio.coroutine
def task_io_1():
    print('{} started...'.format(task_io_1.__name__))
    # 假设这里 io 任务须要耗费 2s 时间
    yield from asyncio.sleep(3)
    print('在我以前,由于 io 异步了,那么久中断去执行另外的任务了,等执行完又来执行我了,{} continue...'.format(task_io_1.__name__))
    return task_io_1.__name__

async def do_some_io_workd(n):
    asyncio.sleep(n)


@asyncio.coroutine
def task_io_2():
    print('{} start...'.format(task_io_2.__name__))
    yield from asyncio.sleep(5)
    print('在我以前,由于 io 异步了,那么久中断去执行另外的任务了,等执行完又来执行我了,{} continue...'.format(task_io_2.__name__))
    return task_io_2.__name__

@time_count
def main():
    tasks = [task_io_1(),task_io_2()]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()

if __name__ == '__main__':
    main()

相关文章
相关标签/搜索