• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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