如何在CPython中实现生成器和协同路由?

如何在CPython中实现生成器和协同路由?,python,coroutine,Python,Coroutine,我已经读到在CPython中,解释器堆栈(为达到这一点而调用的Python函数列表)与C堆栈(解释器自己的代码中调用的C函数列表)混合在一起。如果是这样,那么生成器和协同程序是如何实现的?他们如何记得自己的执行状态?CPython是否将每个生成器/协同程序的堆栈复制到操作系统堆栈中或从中复制?或者CPython只是将生成器的最顶层堆栈帧保留在堆上,因为生成器只能从最顶层的帧生成?yield指令将当前执行的上下文作为闭包,并将其转换为自己的活动对象。此对象有一个\uuu iter\uu方法,该方法

我已经读到在CPython中,解释器堆栈(为达到这一点而调用的Python函数列表)与C堆栈(解释器自己的代码中调用的C函数列表)混合在一起。如果是这样,那么生成器和协同程序是如何实现的?他们如何记得自己的执行状态?CPython是否将每个生成器/协同程序的堆栈复制到操作系统堆栈中或从中复制?或者CPython只是将生成器的最顶层堆栈帧保留在堆上,因为生成器只能从最顶层的帧生成?

yield指令将当前执行的上下文作为闭包,并将其转换为自己的活动对象。此对象有一个
\uuu iter\uu
方法,该方法将在该yield语句之后继续


因此,调用堆栈被转换为一个heap对象。

在运行的Python程序中,Python的堆栈和C堆栈混合的概念可能会产生误导

Python堆栈与解释器使用的实际C堆栈完全分离。Python堆栈上的数据结构实际上是完整的Python“frame”对象(甚至可以在运行时进行内省并更改某些属性)。该堆栈由Python虚拟机管理,该虚拟机本身以C语言运行,因此有一个普通的C程序、机器级堆栈


当使用生成器和迭代器时,解释器只需将相应的帧对象存储在Python程序堆栈以外的其他位置,并在继续执行生成器时将其推回到该位置。“其他地方”是生成器对象本身。在生成器对象上调用方法“next”或“send”会导致这种情况发生。

必须澄清C“硬件”堆栈和Python堆栈完全不同,因为这个问题混淆了两者。我的回答澄清了这一点。(@Rudi-你的回答很好,我会留下评论,以便其他到达这里的人也检查这一部分)我在读了这篇文章后查找了它,所以如果其他人感兴趣,这里是。我建议首先阅读这个答案,它有助于理解代码的作用。一些现有的答案和注释声称Python维护一个与VM的C堆栈完全分离的“程序堆栈”。这种说法是错误的。检查链接:Stackless Python存在,但不是主流。理解是这个问题是正确的。近四年后,我意外地回答了自己,我与他人合著了一章,其中包括对生成器和协同程序如何实现的解释:很棒的文章,非常密集。不相关,但。。。在不到4年的时间里,您是如何从询问生成器是如何实现的,到与Guido一起编写关于此主题的书籍章节的?:)哈!实现和维护Motor,这是我为Tornado和asyncio开发的MongoDB驱动程序,这意味着我在过去几年中一直在使用和思考协同程序。我通过阅读CPython源代码(比我担心的更清晰)和Tornado的源代码来满足我的好奇心,然后,当asyncio被编写时,我也读了。另外,我想在会议上发言,这进一步促使我研究协同路由和异步,以便就这个主题进行演讲。