Hi Yury, I'm just starting my exploration into using async/await; all my 'real-world' scenarios are currently hypothetical.
One such hypothetical scenario however is that if I have a server process running, with some set of concurrent connections, each managed by a co-routine. Each co-routine is of some arbitrary complexity e.g: some combination of reading files, reading from database, reading from peripherals. If I notice one of those co-routines appears stuck and not making progress, I'd very much like to debug that, and preferably in a way that doesn't necessarily stop the rest of the server (or even the co-routine that appears stuck). The problem with the "if debug: log(...)" approach is that you need foreknowledge of the fault state occurring; on a busy server you don't want to just be logging every 'switch()'. I guess you could do something like "switch_state[outer_coro] = get_current_stack_frames()" on each switch. To me double book-keeping something that the interpreter already knows seems somewhat wasteful but maybe it isn't really too bad. Cheers, Ben On 29 May 2015 at 23:57, Yury Selivanov <yselivanov...@gmail.com> wrote: > 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 >> >> coro_a = a() >> coro_a.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 gi_frame attribute of coro_a, 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 f_back 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.gi_frame.f_code.co_filename, >> coro.gi_frame.f_lineno)) >> if dis.opname[coro.gi_code.co_code[coro.gi_frame.f_lasti + 1]] == >> 'YIELD_FROM': >> show(coro.gi_frame.f_stack[0]) >> """ >> >> This relies on the fact that an await-ing co-routine will be executing >> a YIELD_FROM instruction. The above code uses a completely >> hypothetical 'f_stack' 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 f_stack 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@python.org >> https://mail.python.org/mailman/listinfo/python-dev >> Unsubscribe: >> https://mail.python.org/mailman/options/python-dev/yselivanov.ml%40gmail.com > > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/benno%40benno.id.au _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com