diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index e6705cfc8..51e86c76f 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -543,6 +543,14 @@ def enter_eventloop(self): self.log.info("Exiting as there is no eventloop") return + from .eventloops import loop_asyncio + + if eventloop is loop_asyncio: + # The kernel already runs on asyncio, so there is nothing to poll. + # Polling every millisecond would only burn CPU (#1532). + self.log.info("Kernel already runs on asyncio; no polling needed") + return + async def advance_eventloop(): # check if eventloop changed: if self.eventloop is not eventloop: diff --git a/tests/test_eventloop.py b/tests/test_eventloop.py index a95d6338d..599361d8d 100644 --- a/tests/test_eventloop.py +++ b/tests/test_eventloop.py @@ -93,6 +93,26 @@ def do_thing(): loop_asyncio(kernel) +@windows_skip +async def test_asyncio_gui_does_not_poll(kernel): + # The kernel already runs on asyncio, so `%gui asyncio` has nothing to poll (#1532). + calls = [] + call_later = kernel.io_loop.call_later + + def counting_call_later(delay, callback, *args, **kwargs): + calls.append(callback) + return call_later(delay, callback, *args, **kwargs) + + kernel.io_loop.call_later = counting_call_later + try: + kernel.eventloop = loop_asyncio + await asyncio.sleep(0.1) + finally: + kernel.eventloop = None + del kernel.io_loop.call_later + assert len(calls) <= 1 + + @windows_skip def test_enable_gui(kernel): enable_gui("tk", kernel)