8.13. Loop control#

Most asyncio scripts never touch the event loop directly – asyncio.run() is enough. This page covers the Loop surface for the cases where it is not: installing an exception handler, running the loop with a different lifecycle than run, or holding on to the loop object for instrumentation.

8.13.1. Getting the loop#

  • asyncio.get_event_loop() – returns the Loop object. Safe to call from inside or outside a coroutine.

  • asyncio.new_event_loop() – on MicroPython, resets the existing loop’s state rather than creating a new one. The note bears repeating: there is exactly one event loop per program.

There is no API for running the loop other than the methods on Loop and asyncio.run().

8.13.2. Running the loop directly#

asyncio.run() is the right entry point for almost every application. Two Loop methods exist for the cases where it is not.

  • run_until_complete() – given an awaitable, run the loop until that awaitable finishes, then return its result. Equivalent to a single asyncio.run() call, with the loop teardown left out.

  • run_forever() – run the loop until stop() is called from inside a task. No top-level awaitable; the application is expected to schedule whatever it needs via asyncio.create_task() before calling run_forever.

The companion methods are stop() (request the loop to stop after the current task finishes) and close() (free the loop’s resources).

8.13.3. Loop-side task creation#

  • create_task() – same operation as asyncio.create_task(). The free function exists so application code does not need a loop reference for the common case; the method exists for instrumentation that already has one.

8.13.4. Exception handlers#

The loop calls a handler when a task raises an exception that nothing in the coroutine call chain has caught – a typical case being a task the application created with asyncio.create_task() and never awaited. The default handler prints a traceback through sys.stderr; the exceptions page showed how to swap it for something custom.

  • set_exception_handler() – install a custom handler. The handler is a callable handler(loop, context) where context is a dict with at least 'message' and usually 'exception' and 'future'.

  • get_exception_handler() – return the currently installed handler, or None if the default is in use.

  • default_exception_handler() – the built-in handler. Useful inside a custom handler that wants to also run the default behaviour (log to flash and print a traceback, for instance).

  • call_exception_handler() – run the currently installed handler with a hand-built context dict. Mostly used by the loop itself; an application rarely needs it.