On Sun, Nov 12, 2017 at 7:27 AM, Guido van Rossum <guido@python.org> wrote:
On Sun, Nov 12, 2017 at 2:53 AM, Chris Jerdonek <chris.jerdonek@gmail.com> wrote:
By the way, since we're already on the subject of asyncio tasks and (truncated) stack traces, this looks like a good opportunity to ask a question that's been on my mind for a while:
There's a mysterious note at the end of the documentation of asyncio.Task's get_stack() method, where it says--
For reasons beyond our control, only one stack frame is returned for a suspended coroutine.
(https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.get_stack )
What does the "For reasons beyond our control" mean? What is it that can possibly be beyond the control of Python?
It's an odd phrasing, but it refers to the fact that a suspended generator frame (which is what a coroutine really is) does not have a "back link" to the frame that called it. Whenever a generator yields (or a coroutine awaits) its frame is disconnected from the current call stack, control is passed to the top frame left on that stack, and the single generator frame is just held on to by the generator object. When you call next() on that, it will be pushed on top of whatever is the current stack (i.e. whatever calls next()), which *may* be a completely different stack configuration than when it was suspended.
It is possible to get the await/yield from stack though, even when a generator/coroutine is suspended, using the gi_yieldfrom / cr_await attributes. Teaching Task.get_stack to do this would be a nice little enhancement. -n -- Nathaniel J. Smith -- https://vorpus.org