| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | .. currentmodule:: asyncio
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =======
 | 
					
						
							|  |  |  | Runners
 | 
					
						
							|  |  |  | =======
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **Source code:** :source:`Lib/asyncio/runners.py`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This section outlines high-level asyncio primitives to run asyncio code.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | They are built on top of an :ref:`event loop <asyncio-event-loop>` with the aim
 | 
					
						
							|  |  |  | to simplify async code usage for common wide-spread scenarios.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. contents::
 | 
					
						
							|  |  |  |    :depth: 1
 | 
					
						
							|  |  |  |    :local: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Running an asyncio Program
 | 
					
						
							|  |  |  | ==========================
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 23:48:51 +05:30
										 |  |  | .. function:: run(coro, *, debug=None, loop_factory=None)
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    Execute the :term:`coroutine` *coro* and return the result.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This function runs the passed coroutine, taking care of
 | 
					
						
							|  |  |  |    managing the asyncio event loop, *finalizing asynchronous
 | 
					
						
							| 
									
										
										
										
											2022-09-28 23:09:42 +05:30
										 |  |  |    generators*, and closing the executor.
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This function cannot be called when another asyncio event loop is
 | 
					
						
							|  |  |  |    running in the same thread.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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
 | 
					
						
							|  |  |  |    :ref:`asyncio-debug-mode` settings.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 23:48:51 +05:30
										 |  |  |    If *loop_factory* is not ``None``, it is used to create a new event loop;
 | 
					
						
							|  |  |  |    otherwise :func:`asyncio.new_event_loop` is used. The loop is closed at the end.
 | 
					
						
							|  |  |  |    This function should be used as a main entry point for asyncio programs,
 | 
					
						
							|  |  |  |    and should ideally only be called once. It is recommended to use
 | 
					
						
							|  |  |  |    *loop_factory* to configure the event loop instead of policies.
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 23:09:42 +05:30
										 |  |  |    The executor is given a timeout duration of 5 minutes to shutdown.
 | 
					
						
							|  |  |  |    If the executor hasn't finished within that duration, a warning is
 | 
					
						
							|  |  |  |    emitted and the executor is closed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  |    Example::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        async def main():
 | 
					
						
							|  |  |  |            await asyncio.sleep(1)
 | 
					
						
							|  |  |  |            print('hello')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        asyncio.run(main())
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. versionadded:: 3.7
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. versionchanged:: 3.9
 | 
					
						
							|  |  |  |       Updated to use :meth:`loop.shutdown_default_executor`.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. versionchanged:: 3.10
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *debug* is ``None`` by default to respect the global debug mode settings.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 23:48:51 +05:30
										 |  |  |    .. versionchanged:: 3.12
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Added *loop_factory* parameter.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Runner context manager
 | 
					
						
							|  |  |  | ======================
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 00:26:23 +02:00
										 |  |  | .. class:: Runner(*, debug=None, loop_factory=None)
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    A context manager that simplifies *multiple* async function calls in the same
 | 
					
						
							|  |  |  |    context.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Sometimes several top-level async functions should be called in the same :ref:`event
 | 
					
						
							|  |  |  |    loop <asyncio-event-loop>` and :class:`contextvars.Context`.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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
 | 
					
						
							|  |  |  |    :ref:`asyncio-debug-mode` settings.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 00:26:23 +02:00
										 |  |  |    *loop_factory* could be used for overriding the loop creation.
 | 
					
						
							| 
									
										
										
										
											2022-08-14 21:23:34 +05:30
										 |  |  |    It is the responsibility of the *loop_factory* to set the created loop as the
 | 
					
						
							|  |  |  |    current one. By default :func:`asyncio.new_event_loop` is used and set as
 | 
					
						
							|  |  |  |    current event loop with :func:`asyncio.set_event_loop` if *loop_factory* is ``None``.
 | 
					
						
							| 
									
										
										
										
											2022-03-24 21:51:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    Basically, :func:`asyncio.run()` example can be rewritten with the runner usage::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def main():
 | 
					
						
							|  |  |  |             await asyncio.sleep(1)
 | 
					
						
							|  |  |  |             print('hello')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with asyncio.Runner() as runner:
 | 
					
						
							|  |  |  |             runner.run(main())
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. versionadded:: 3.11
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. method:: run(coro, *, context=None)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Run a :term:`coroutine <coroutine>` *coro* in the embedded loop.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Return the coroutine's result or raise its exception.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       An optional keyword-only *context* argument allows specifying a
 | 
					
						
							|  |  |  |       custom :class:`contextvars.Context` for the *coro* to run in.
 | 
					
						
							|  |  |  |       The runner's default context is used if ``None``.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       This function cannot be called when another asyncio event loop is
 | 
					
						
							|  |  |  |       running in the same thread.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. method:: close()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Close the runner.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Finalize asynchronous generators, shutdown default executor, close the event loop
 | 
					
						
							|  |  |  |       and release embedded :class:`contextvars.Context`.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. method:: get_loop()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Return the event loop associated with the runner instance.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    .. note::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       :class:`Runner` uses the lazy initialization strategy, its constructor doesn't
 | 
					
						
							|  |  |  |       initialize underlying low-level structures.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Embedded *loop* and *context* are created at the :keyword:`with` body entering
 | 
					
						
							|  |  |  |       or the first call of :meth:`run` or :meth:`get_loop`.
 | 
					
						
							| 
									
										
										
										
											2022-03-30 15:15:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Handling Keyboard Interruption
 | 
					
						
							|  |  |  | ==============================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. versionadded:: 3.11
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When :const:`signal.SIGINT` is raised by :kbd:`Ctrl-C`, :exc:`KeyboardInterrupt`
 | 
					
						
							|  |  |  | exception is raised in the main thread by default. However this doesn't work with
 | 
					
						
							|  |  |  | :mod:`asyncio` because it can interrupt asyncio internals and can hang the program from
 | 
					
						
							|  |  |  | exiting.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To mitigate this issue, :mod:`asyncio` handles :const:`signal.SIGINT` as follows:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. :meth:`asyncio.Runner.run` installs a custom :const:`signal.SIGINT` handler before
 | 
					
						
							|  |  |  |    any user code is executed and removes it when exiting from the function.
 | 
					
						
							|  |  |  | 2. The :class:`~asyncio.Runner` creates the main task for the passed coroutine for its
 | 
					
						
							|  |  |  |    execution.
 | 
					
						
							|  |  |  | 3. When :const:`signal.SIGINT` is raised by :kbd:`Ctrl-C`, the custom signal handler
 | 
					
						
							|  |  |  |    cancels the main task by calling :meth:`asyncio.Task.cancel` which raises
 | 
					
						
							| 
									
										
										
										
											2022-05-02 13:43:52 -06:00
										 |  |  |    :exc:`asyncio.CancelledError` inside the main task.  This causes the Python stack
 | 
					
						
							| 
									
										
										
										
											2022-03-30 15:15:06 +03:00
										 |  |  |    to unwind, ``try/except`` and ``try/finally`` blocks can be used for resource
 | 
					
						
							|  |  |  |    cleanup.  After the main task is cancelled, :meth:`asyncio.Runner.run` raises
 | 
					
						
							|  |  |  |    :exc:`KeyboardInterrupt`.
 | 
					
						
							|  |  |  | 4. A user could write a tight loop which cannot be interrupted by
 | 
					
						
							|  |  |  |    :meth:`asyncio.Task.cancel`, in which case the second following :kbd:`Ctrl-C`
 | 
					
						
							|  |  |  |    immediately raises the :exc:`KeyboardInterrupt` without cancelling the main task.
 |