Consider this program:
import trio
import contextlib
async def background():
assert False
async def main():
async with contextlib.AsyncExitStack() as stack:
n = await stack.enter_async_context(trio.open_nursery())
n.start_soon(background)
await trio.sleep_forever()
trio.run(main)
We get an AssertionError
as expected, but the traceback looks like this:
Traceback (most recent call last):
File "/Users/dphoyes/devel/experiment.py", line 11, in main
await trio.sleep_forever()
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/trio/_timeouts.py", line 40, in sleep_forever
await trio.lowlevel.wait_task_rescheduled(lambda _: trio.lowlevel.Abort.SUCCEEDED)
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/trio/_core/_traps.py", line 166, in wait_task_rescheduled
return (await _async_yield(WaitTaskRescheduled(abort_func))).unwrap()
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/outcome/_impl.py", line 138, in unwrap
raise captured_error
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/trio/_core/_run.py", line 1172, in raise_cancel
raise Cancelled._create()
trio.Cancelled: Cancelled
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/dphoyes/devel/experiment.py", line 13, in <module>
trio.run(main)
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/trio/_core/_run.py", line 1932, in run
raise runner.main_task_outcome.error
File "/Users/dphoyes/devel/experiment.py", line 11, in main
await trio.sleep_forever()
File "/opt/homebrew/Cellar/python@3.9/3.9.4/Frameworks/Python.framework/Versions/3.9/lib/python3.9/contextlib.py", line 651, in __aexit__
raise exc_details[1]
File "/opt/homebrew/Cellar/python@3.9/3.9.4/Frameworks/Python.framework/Versions/3.9/lib/python3.9/contextlib.py", line 634, in __aexit__
cb_suppress = await cb(*exc_details)
File "/Users/dphoyes/devel/venv/lib/python3.9/site-packages/trio/_core/_run.py", line 815, in __aexit__
raise combined_error_from_nursery
File "/Users/dphoyes/devel/experiment.py", line 5, in background
assert False
AssertionError
In other words, the AssertionError
's __context__
is being set to that of the Cancelled
exception. If we swap the use of AsyncExitStack
out for the equivalent async with trio.open_nursery() as n:
, we get the much simpler traceback that we'd expect.
This is admittedly a relatively benign issue, and it's not clear to me whether it's actually Trio at fault here or contextlib. In my real app though, there's enough nesting of cancellations to make this turn a 46 line traceback into a 42227 line one, which makes debugging a bit "interesting". I've worked around it by eliminating all usage of AsyncExitStack
, but I thought it worth sharing anyway.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4