[Async-sig] task.result() and exception traceback display

Nathaniel Smith njs at pobox.com
Mon Dec 25 03:48:15 EST 2017


I haven't thought about this enough to have an opinion about whether
this is correct or how it could be improved, but I can explain why
you're seeing what you're seeing :-).

The traceback is really a trace of where the exception went after it
was raised, with new lines added to the top as it bubbles out. So the
bottom line is the 'raise' statement, because that's where it was
created, and then it bubbled onto the 'call 1' line and was caught.
Then it was raised again and bubbled onto the 'call 2' line. Etc. So
you should think of it not as a snapshot of your stack when it was
created, but as a travelogue.

-n

On Sun, Dec 24, 2017 at 9:55 PM, Chris Jerdonek
<chris.jerdonek at gmail.com> wrote:
> Hi,
>
> I noticed that if a task in asyncio raises an exception, then the
> displayed traceback can be "polluted" by intermediate calls to
> task.result().  Also, the calls to task.result() can appear out of
> order relative to each other and to other lines.
>
> Here is an example:
>
>     import asyncio
>
>     async def raise_error():
>         raise ValueError()
>
>     async def main():
>         task = asyncio.ensure_future(raise_error())
>
>         try:
>             await task  # call 1
>         except Exception:
>             pass
>
>         try:
>             task.result()  # call 2
>         except Exception:
>             pass
>
>         task.result()  # call 3
>
>     asyncio.get_event_loop().run_until_complete(main())
>
> The above outputs--
>
>     Traceback (most recent call last):
>       File "test.py", line 24, in <module>
>         asyncio.get_event_loop().run_until_complete(main())
>       File "/Users/.../3.6.4rc1/lib/python3.6/asyncio/base_events.py",
>           line 467, in run_until_complete
>         return future.result()
>       File "test.py", line 21, in main
>         task.result()  # call 3
>       File "test.py", line 17, in main
>         task.result()  # call 2
>       File "test.py", line 12, in main
>         await task  # call 1
>       File "test.py", line 5, in raise_error
>         raise ValueError()
>     ValueError
>
> Notice that the "call 2" line appears in the traceback, even though it
> doesn't come into play in the exception.  Also, the lines don't obey
> the "most recent call last" rule.  If this rule were followed, it
> should be something more like--
>
>     Traceback (most recent call last):
>       File "test.py", line 24, in <module>
>         asyncio.get_event_loop().run_until_complete(main())
>       File "/Users/.../3.6.4rc1/lib/python3.6/asyncio/base_events.py",
>           line 467, in run_until_complete
>         return future.result()
>       File "test.py", line 12, in main
>         await task  # call 1
>       File "test.py", line 5, in raise_error
>         raise ValueError()
>       File "test.py", line 17, in main
>         task.result()  # call 2
>       File "test.py", line 21, in main
>         task.result()  # call 3
>     ValueError
>
> If people agree there's an issue along these lines, I can file an
> issue in the tracker. I didn't seem to find one when searching for
> open issues with search terms like "asyncio traceback".
>
> Thanks,
> --Chris
> _______________________________________________
> Async-sig mailing list
> Async-sig at python.org
> https://mail.python.org/mailman/listinfo/async-sig
> Code of Conduct: https://www.python.org/psf/codeofconduct/



-- 
Nathaniel J. Smith -- https://vorpus.org


More information about the Async-sig mailing list