[Python-Dev] Obtaining stack-frames from co-routine objects (original) (raw)

Yury Selivanov yselivanov.ml at gmail.com
Fri May 29 15:57:24 CEST 2015


Hi Ben,

Is there any real-world scenario where you would need this?

It looks like this can help with debugging, somehow, but the easiest solution is to put a "if debug: log(...)" before "yield" in your "switch()" function. You'll have a perfect traceback there.

Thanks, Yury

On 2015-05-29 12:46 AM, Ben Leslie wrote:

Hi all,

Apologies in advance; I'm not a regular, and this may have been handled already (but I couldn't find it when searching). I've been using the new async/await functionality (congrats again to Yury on getting that through!), and I'd like to get a stack trace between the place at which blocking occurs and the outer co-routine. For example, consider this code: """ async def a(): await b() async def b(): await switch() @types.coroutine def switch(): yield coroa = a() coroa.send(None) """ At this point I'd really like to be able to somehow get a stack trace similar to: test.py:2 test.py:4 test.py:9 Using the giframe attribute of coroa, I can get the line number of the outer frame (e.g.: line 2), but from there there is no way to descend the stack to reach the actual yield point. I thought that perhaps the switch() co-routine could yield the frame object returned from inspect.currentframe(), however once that function yields that frame object has fback changed to None. A hypothetical approach would be to work the way down form the outer-frame, but that requires getting access to the co-routine object that the outer-frame is currently await-ing. Some hypothetical code could be: """ def show(coro): print("{}:{}".format(coro.giframe.fcode.cofilename, coro.giframe.flineno)) if dis.opname[coro.gicode.cocode[coro.giframe.flasti + 1]] == 'YIELDFROM': show(coro.giframe.fstack[0]) """ This relies on the fact that an await-ing co-routine will be executing a YIELDFROM instruction. The above code uses a completely hypothetical 'fstack' property of frame objects to pull the co-routine object which a co-routine is currently await-ing from the stack. I've implemented a proof-of-concept fstack property in the frameobject.c just to test out the above code, and it seems to work. With all that, some questions: 1) Does anyone else see value in trying to get the stack-trace down to the actual yield point? 2) Is there a different way of doing it that doesn't require changes to Python internals? 3) Assuming no to #2 is there a better way of getting the information compared to the pretty hacking byte-code/stack inspection? Thanks, Ben


Python-Dev mailing list Python-Dev at python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/yselivanov.ml%40gmail.com



More information about the Python-Dev mailing list