python之协程
协程用来处理并发,多线程和多进程用来处理并行
1. 定义协程
协程优势:
执行效率极高,因为子程序(函数)切换不是线程切换,由程序自身控制,没有切换线程的开销。
不需要多线程的锁机制,因为只有一个线程,也不存在竞争资源的问题,当然也就不需要对资源加锁保护,因此执行效率高很多。
定义协程有2种常用的方式
- 在定义函数的时候加上async作为前缀
- 使用python装饰器。
运行协程
协程函数的调用与普通函数不同,要让协程对象运行的话,常用的方式有2种
- 在另一个已经运行的协程用‘await’等待它(或者yield from)
- 通过 ‘ensure_future’ 函数计划它的执行
简单来说,只有loop运行了,协程才可能运行。所以在运行协程之前,必须先拿到当前线程缺省的loop,然后把协程对象交给loop.run_until_complete,协程对象随后会在loop里得到运行。
多个协程
在实际运行异步中,往往是有多个协程,同时在一个loop里运行。于是需要使用asyncio.gather函数把多个协程交给loop。
loop.run_until_complete(asyncio.gather(do_some_work(1), do_some_work(3)))
当然协程一多起来,一条语句写起来就不方便了,可以先把协程存在列表里。
coros = [do_some_work(1), do_some_work(3)]
loop.run_until_complete(asyncio.gather(*coros))
由于这两个协程是并发运行的,所以等待时间并不是1+3=4,而是以耗时比较长的那个。
上面也提到run_until_complete的参数是future,而gather起聚合的作用,把多个futures包装成一个future,因为loop.run_until_complete只接受单个future。上述代码也可以改为:
coros = [asyncio.ensure_future(do_some_work(1)),
asyncio.ensure_future(do_some_work(3))]
loop.run_until_complete(asyncio.gather(*coros))