接触Python协程也有一段时间了,网上的资料大多是从生成器开始介绍,这给了我很大的困惑。好在根据这段时间的学习,大概有了一个Python协程的印象,所以把一些想法写在此处,如有错误还请大家指出,我也好及时修改,避免误导广大读者。
首先我想说一下为什么大部分教程要从生成器开始讲起,因为生成器的yield from 给我们提供了一种机制,即可以暂时中断一个函数的执行,此时这个函数的执行状态是保持在内存中的,并且允许用户在适当的时候唤起以继续执行此函数。因此我们把这样一种机制称作协程。
对于生成器和协程,理解到此处就OK了,不必过分纠结他的实现机制,以免钻牛角尖。
下面就是讲解asyncio机制了。对于阻塞调用,尤其是IO操作(此处特指网络IO),传统的做法是人为实现多线程(在主线程中创建子线程),然后在子线程中执行阻塞调用。不必担心阻塞线程占用CPU资源,由于Python有GIL,对于阻塞线程,Python会自动切换到其他不是阻塞状态的线程,然后调入到CPU中执行,因此同一时间只有一个线程执行,不存在占用CPU的情况。这种实现的问题是一旦进入高并发场景,比如同一时间有一万个阻塞线程,Python一次创建并维持这么多子线程这一过程本身是非常耗费系统资源的,因此在高并发场景下不能使用多线程方案。具体的操作过程可参考Python标准库concurrency.future,例子如下:
def thread_blocking_io_call():
request = pre_call() # 在阻塞调用前进行的预处理
resp