1.. currentmodule:: asyncio 2 3 4======= 5Runners 6======= 7 8**Source code:** :source:`Lib/asyncio/runners.py` 9 10 11This section outlines high-level asyncio primitives to run asyncio code. 12 13They are built on top of an :ref:`event loop <asyncio-event-loop>` with the aim 14to simplify async code usage for common wide-spread scenarios. 15 16.. contents:: 17 :depth: 1 18 :local: 19 20 21 22Running an asyncio Program 23========================== 24 25.. function:: run(coro, *, debug=None, loop_factory=None) 26 27 Execute the :term:`coroutine` *coro* and return the result. 28 29 This function runs the passed coroutine, taking care of 30 managing the asyncio event loop, *finalizing asynchronous 31 generators*, and closing the executor. 32 33 This function cannot be called when another asyncio event loop is 34 running in the same thread. 35 36 If *debug* is ``True``, the event loop will be run in debug mode. ``False`` disables 37 debug mode explicitly. ``None`` is used to respect the global 38 :ref:`asyncio-debug-mode` settings. 39 40 If *loop_factory* is not ``None``, it is used to create a new event loop; 41 otherwise :func:`asyncio.new_event_loop` is used. The loop is closed at the end. 42 This function should be used as a main entry point for asyncio programs, 43 and should ideally only be called once. It is recommended to use 44 *loop_factory* to configure the event loop instead of policies. 45 Passing :class:`asyncio.EventLoop` allows running asyncio without the 46 policy system. 47 48 The executor is given a timeout duration of 5 minutes to shutdown. 49 If the executor hasn't finished within that duration, a warning is 50 emitted and the executor is closed. 51 52 Example:: 53 54 async def main(): 55 await asyncio.sleep(1) 56 print('hello') 57 58 asyncio.run(main()) 59 60 .. versionadded:: 3.7 61 62 .. versionchanged:: 3.9 63 Updated to use :meth:`loop.shutdown_default_executor`. 64 65 .. versionchanged:: 3.10 66 67 *debug* is ``None`` by default to respect the global debug mode settings. 68 69 .. versionchanged:: 3.12 70 71 Added *loop_factory* parameter. 72 73 74Runner context manager 75====================== 76 77.. class:: Runner(*, debug=None, loop_factory=None) 78 79 A context manager that simplifies *multiple* async function calls in the same 80 context. 81 82 Sometimes several top-level async functions should be called in the same :ref:`event 83 loop <asyncio-event-loop>` and :class:`contextvars.Context`. 84 85 If *debug* is ``True``, the event loop will be run in debug mode. ``False`` disables 86 debug mode explicitly. ``None`` is used to respect the global 87 :ref:`asyncio-debug-mode` settings. 88 89 *loop_factory* could be used for overriding the loop creation. 90 It is the responsibility of the *loop_factory* to set the created loop as the 91 current one. By default :func:`asyncio.new_event_loop` is used and set as 92 current event loop with :func:`asyncio.set_event_loop` if *loop_factory* is ``None``. 93 94 Basically, :func:`asyncio.run` example can be rewritten with the runner usage:: 95 96 async def main(): 97 await asyncio.sleep(1) 98 print('hello') 99 100 with asyncio.Runner() as runner: 101 runner.run(main()) 102 103 .. versionadded:: 3.11 104 105 .. method:: run(coro, *, context=None) 106 107 Run a :term:`coroutine <coroutine>` *coro* in the embedded loop. 108 109 Return the coroutine's result or raise its exception. 110 111 An optional keyword-only *context* argument allows specifying a 112 custom :class:`contextvars.Context` for the *coro* to run in. 113 The runner's default context is used if ``None``. 114 115 This function cannot be called when another asyncio event loop is 116 running in the same thread. 117 118 .. method:: close() 119 120 Close the runner. 121 122 Finalize asynchronous generators, shutdown default executor, close the event loop 123 and release embedded :class:`contextvars.Context`. 124 125 .. method:: get_loop() 126 127 Return the event loop associated with the runner instance. 128 129 .. note:: 130 131 :class:`Runner` uses the lazy initialization strategy, its constructor doesn't 132 initialize underlying low-level structures. 133 134 Embedded *loop* and *context* are created at the :keyword:`with` body entering 135 or the first call of :meth:`run` or :meth:`get_loop`. 136 137 138Handling Keyboard Interruption 139============================== 140 141.. versionadded:: 3.11 142 143When :const:`signal.SIGINT` is raised by :kbd:`Ctrl-C`, :exc:`KeyboardInterrupt` 144exception is raised in the main thread by default. However this doesn't work with 145:mod:`asyncio` because it can interrupt asyncio internals and can hang the program from 146exiting. 147 148To mitigate this issue, :mod:`asyncio` handles :const:`signal.SIGINT` as follows: 149 1501. :meth:`asyncio.Runner.run` installs a custom :const:`signal.SIGINT` handler before 151 any user code is executed and removes it when exiting from the function. 1522. The :class:`~asyncio.Runner` creates the main task for the passed coroutine for its 153 execution. 1543. When :const:`signal.SIGINT` is raised by :kbd:`Ctrl-C`, the custom signal handler 155 cancels the main task by calling :meth:`asyncio.Task.cancel` which raises 156 :exc:`asyncio.CancelledError` inside the main task. This causes the Python stack 157 to unwind, ``try/except`` and ``try/finally`` blocks can be used for resource 158 cleanup. After the main task is cancelled, :meth:`asyncio.Runner.run` raises 159 :exc:`KeyboardInterrupt`. 1604. A user could write a tight loop which cannot be interrupted by 161 :meth:`asyncio.Task.cancel`, in which case the second following :kbd:`Ctrl-C` 162 immediately raises the :exc:`KeyboardInterrupt` without cancelling the main task. 163