tutorial programming español await asyncio async python coroutine

programming - python async await



¿Cómo se implementan los generadores y coroutines en CPython? (3)

He leído que en CPython, la pila de intérpretes (la lista de funciones de Python llamada para llegar a este punto) se mezcla con la pila C (la lista de funciones C que se llamaron en el propio código del intérprete). Si es así, ¿cómo se implementan los generadores y coroutines? ¿Cómo recuerdan su estado de ejecución? ¿CPython copia la pila de cada generador / coroutine desde y hacia una pila de SO? ¿O CPython simplemente mantiene el marco de pila superior del generador en el montón, ya que el generador solo puede ceder desde ese marco superior?


Algunas respuestas y comentarios existentes afirman que Python mantiene una "pila de programas" que está completamente separada de la pila C de la VM. Esta afirmación es incorrecta.

Verifique el enlace: http://en.wikipedia.org/wiki/Stackless_Python

Stackless Python existe, pero no es la corriente principal. El entendimiento es que la pregunta es correcta.


La noción de que la pila de Python y la pila de C en un programa en ejecución de Python están entremezcladas puede ser engañosa.

La pila de Python es algo completamente separado de la pila de C real utilizada por el intérprete. Las estructuras de datos en la pila de Python son en realidad objetos completos de "marco" de Python (que incluso pueden ser inspeccionados y tienen algunos atributos modificados en tiempo de ejecución). Esta pila es administrada por la máquina virtual de Python, que se ejecuta en C y tiene un programa C normal, nivel de máquina, pila.

Cuando se utilizan generadores e iteradores, el intérprete simplemente almacena el objeto de marco respectivo en otro lugar que no sea en la pila de programas de Python, y lo empuja hacia atrás cuando se reanuda la ejecución del generador. Este "otro lugar" es el propio objeto generador. Llamar al método "siguiente" o "enviar" al objeto generador hace que esto ocurra.


La instrucción de yield toma el contexto de ejecución actual como un cierre, y lo transforma en un objeto vivo propio. Este objeto tiene un método __iter__ que continuará después de esta declaración de rendimiento.

Entonces, la pila de llamadas se transforma en un objeto de montón.