Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。gevent是第三方库,通过greenlet实现协程,其基本思想是:当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:1、gevent协程适合I/O密集,不适合CPU密集。 3、gevent协程无法发挥多核优势,事实上,协程只是以单线程的方式在运行。 3、子程序就是协程的一种特例
从下面例子入道, 单线程 函数级 切换任务执行,支持大量并发, 而 线程 以及 进程都是内核级别的
# -*- coding: utf-8 -*-__author__ = 'Frank Li'import asynciofrom functools import wrapsimport timedef 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.coroutinedef 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.coroutinedef 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_countdef 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()