在 Python 核心开发人员 Brett Cannon 的一篇文章《 How the heck does async/await work in Python 3.5?》中提到:
One very key point I want to make about the difference between a generator-based coroutine and an async one is that only generator-based coroutines can actually pause execution and force something to be sent down to the event loop.
之后总结中还有一句:
You can only make a coroutine call chain pause with a generator-based coroutine.
对应的翻译版在这里:《[译] Python 3.5 协程究竟是个啥》,引用如下:
关于基于生成器的协程和 async 定义的协程之间的差异,我想说明的关键点是只有基于生成器的协程可以真正的暂停执行并强制性返回给事件循环。
你只能通过基于生成器的定义来实现协程的暂停。
在我的理解中,基于生成器的协程使用 yield from 语句,async 定义的协程使用 await 语句,虽然两者可以接受的对象不同(具体原文中有详细描述),但是两者的作用应该是一样的啊:都是暂停当前协程的执行,转交出执行权,直到 yield from 或者 await 的对象执行完成后再返回,继续执行后面的语句。
对此,PEP-492 也有提,下面是其中提到的例子:
async def read_data(db):
data = await db.fetch('SELECT ...')
...
await, similarly to yield from , suspends execution of read_data coroutine until db.fetch awaitable completes and returns the result data.
It uses the yield from implementation with an extra step of validating its argument.
也就是说,await应该使用了yield from类似的实现,作用也是暂停当前执行流程。那么,为啥await不能“真正的暂停执行并强制性返回给事件循环”?
一个脑洞:难道是因为await将执行权转交给了后面的对象,但是并没有转交给作为调度者的消息循环?