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:

"

"

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