Why are async runners created in debug mode? (original) (raw)
My apologies if posting to the incorrect location.
See async_case.py ln121. cpython/Lib/unittest/async_case.py at c3648f4e4a12ec6efe65684facfcd08996e550ca · python/cpython · GitHub
def _setupAsyncioRunner(self):
assert self._asyncioRunner is None, 'asyncio runner is already initialized'
runner = asyncio.Runner(debug=True)
self._asyncioRunner = runner
Setting debug=true here causes asyncio debug logs to be poured out on async unit tests if logging.basicLogging is configured.
Seems like this honors older logic that set the loop to debug:
See line 114 at this commit.
def _setupAsyncioLoop(self):
assert self._asyncioTestLoop is None
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.set_debug(True)
...
The commit does not explain the rationale for this. It seems like it could have been leaked from development by mistake?
Thanks.
ZeroIntensity (Peter Bierma) April 16, 2025, 2:29am 2
I would assume that it’s because it makes debugging easier when tests fail.
kchanivecky (Karel Chanivecky) April 16, 2025, 6:07pm 3
That should not be it:
asyncio.Runner:
"
If debug is True
, the event loop will be run in debug mode. False
disables debug mode explicitly. None
is used to respect the global Debug Mode settings.
"
Debug Mode:
When the debug mode is enabled:
"
- asyncio checks for coroutines that were not awaited and logs them; this mitigates the “forgotten await” pitfall.
- Many non-threadsafe asyncio APIs (such as
loop.call_soon()
and [loop.call_at()
methods) raise an exception if they are called from a wrong thread. - The execution time of the I/O selector is logged if it takes too long to perform an I/O operation.
- Callbacks taking longer than 100 milliseconds are logged. The
loop.slow_callback_duration
attribute can be used to set the minimum execution duration in seconds that is considered “slow”.
"
In the context of unit testing only the non-threadsafe guard seems appropriate. Most of the time unit tests are run in an automated manner and their output will not be inspected unless the test actually fails. Even for the non-threadsafe guard it seems a stretch, as the developer may be doing this intentionally.
It seems to me this setting should be configurable.
kchanivecky (Karel Chanivecky) May 1, 2025, 5:34pm 4
Two work arounds. First:
Override asyncSetUp() adding:
asyncio.get_running_loop().set_debug(False)
Or:
In Python 3.13 Support setting the loop_factory in IsolatedAsyncioTestCase was added.
You can set a loop factory in your test cases that return a wrapper around the asyncio.EventLoop. The wrapper should override loop.set_debug(*enabled: bool) so that it is ignored