python 3.7 async异步编程极简入门

 

  1. 首先,如图是使用async await语法实现的一个和串行程序等价的程序。所有的异步函数声明要加async。

    在一个async函数内,异步调用需要使用await或者其它方式“异步等待”。

    要运行一个async函数,需要使用asyncio.run来执行。

    这个程序还没有发挥出async的优势,只是用于说明基本语法。

    python 3.7 async异步编程极简入门

  2. 如图是和上述async-await版本完全等价的串行程序。执行顺序是完全相同的。

    使用传统阻塞式的time.sleep代替了异步版本asyncio.sleep。

    python 3.7 async异步编程极简入门

  3. 如果我们要理解async有什么好处,不妨先对执行代码记个时,如图。

    可以看到,三个my_task都执行完毕总共花了2*3=6秒。

    python 3.7 async异步编程极简入门

  4. 现在,我们对一开始的那个async-await的版本同样插入计时函数。由于这个版本和串行等价,我们看到三个my_task执行时间一样,共2*3=6秒。

    我们注意到,这是因为三个my_task都用await按照顺序等待,下面将改进之。

    python 3.7 async异步编程极简入门

  5. 如果用三个await按照顺序等待,浪费了时间,第一个my_task陷入sleep开始等待时,完全可以启动第二个my_task。

    改进如图,使用一个await等待3个,3个my_task使用asyncio.create_task依次创建,用asyncio.gether收集。

    我们看到,执行3个任务总共2秒。看print输出,是3个先都启动,然后3个都结束。

    python 3.7 async异步编程极简入门

  6. async-await机制并非多线程多进程等方式,而是单线程实现的。async-await用于描述控制流何时切换。

    一个异步调用必须将其awaited。当async函数进入等待时,调用async函数的一方会保存现场,并层层传导,层层暂停返回。我们想象运行树,从造成等待的叶子节点(I/O等待,网络等待,定时等待..)逐层返回并冻结执行现场,然后接着运行其它任务。

    虽然只有一个线程,但是它在多个async任务之间按照设定好的方式interleaving,提升了CPU的繁忙程度和多任务处理。

     

    如果我们不await一个async调用,会有如图警告,函数不会暂定现场,不会再回到该调用点。

    python 3.7 async异步编程极简入门