• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. currentmodule:: asyncio
2
3
4.. _asyncio-policies:
5
6========
7Policies
8========
9
10An event loop policy is a global object
11used to get and set the current :ref:`event loop <asyncio-event-loop>`,
12as well as create new event loops.
13The default policy can be :ref:`replaced <asyncio-policy-get-set>` with
14:ref:`built-in alternatives <asyncio-policy-builtin>`
15to use different event loop implementations,
16or substituted by a :ref:`custom policy <asyncio-custom-policies>`
17that can override these behaviors.
18
19The :ref:`policy object <asyncio-policy-objects>`
20gets and sets a separate event loop per *context*.
21This is per-thread by default,
22though custom policies could define *context* differently.
23
24Custom event loop policies can control the behavior of
25:func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop`.
26
27Policy objects should implement the APIs defined
28in the :class:`AbstractEventLoopPolicy` abstract base class.
29
30
31.. _asyncio-policy-get-set:
32
33Getting and Setting the Policy
34==============================
35
36The following functions can be used to get and set the policy
37for the current process:
38
39.. function:: get_event_loop_policy()
40
41   Return the current process-wide policy.
42
43.. function:: set_event_loop_policy(policy)
44
45   Set the current process-wide policy to *policy*.
46
47   If *policy* is set to ``None``, the default policy is restored.
48
49
50.. _asyncio-policy-objects:
51
52Policy Objects
53==============
54
55The abstract event loop policy base class is defined as follows:
56
57.. class:: AbstractEventLoopPolicy
58
59   An abstract base class for asyncio policies.
60
61   .. method:: get_event_loop()
62
63      Get the event loop for the current context.
64
65      Return an event loop object implementing the
66      :class:`AbstractEventLoop` interface.
67
68      This method should never return ``None``.
69
70      .. versionchanged:: 3.6
71
72   .. method:: set_event_loop(loop)
73
74      Set the event loop for the current context to *loop*.
75
76   .. method:: new_event_loop()
77
78      Create and return a new event loop object.
79
80      This method should never return ``None``.
81
82   .. method:: get_child_watcher()
83
84      Get a child process watcher object.
85
86      Return a watcher object implementing the
87      :class:`AbstractChildWatcher` interface.
88
89      This function is Unix specific.
90
91      .. deprecated:: 3.12
92
93   .. method:: set_child_watcher(watcher)
94
95      Set the current child process watcher to *watcher*.
96
97      This function is Unix specific.
98
99      .. deprecated:: 3.12
100
101
102.. _asyncio-policy-builtin:
103
104asyncio ships with the following built-in policies:
105
106
107.. class:: DefaultEventLoopPolicy
108
109   The default asyncio policy.  Uses :class:`SelectorEventLoop`
110   on Unix and :class:`ProactorEventLoop` on Windows.
111
112   There is no need to install the default policy manually. asyncio
113   is configured to use the default policy automatically.
114
115   .. versionchanged:: 3.8
116
117      On Windows, :class:`ProactorEventLoop` is now used by default.
118
119   .. deprecated:: 3.12
120      The :meth:`get_event_loop` method of the default asyncio policy now emits
121      a :exc:`DeprecationWarning` if there is no current event loop set and it
122      decides to create one.
123      In some future Python release this will become an error.
124
125
126.. class:: WindowsSelectorEventLoopPolicy
127
128   An alternative event loop policy that uses the
129   :class:`SelectorEventLoop` event loop implementation.
130
131   .. availability:: Windows.
132
133
134.. class:: WindowsProactorEventLoopPolicy
135
136   An alternative event loop policy that uses the
137   :class:`ProactorEventLoop` event loop implementation.
138
139   .. availability:: Windows.
140
141
142.. _asyncio-watchers:
143
144Process Watchers
145================
146
147A process watcher allows customization of how an event loop monitors
148child processes on Unix. Specifically, the event loop needs to know
149when a child process has exited.
150
151In asyncio, child processes are created with
152:func:`create_subprocess_exec` and :meth:`loop.subprocess_exec`
153functions.
154
155asyncio defines the :class:`AbstractChildWatcher` abstract base class, which child
156watchers should implement, and has four different implementations:
157:class:`ThreadedChildWatcher` (configured to be used by default),
158:class:`MultiLoopChildWatcher`, :class:`SafeChildWatcher`, and
159:class:`FastChildWatcher`.
160
161See also the :ref:`Subprocess and Threads <asyncio-subprocess-threads>`
162section.
163
164The following two functions can be used to customize the child process watcher
165implementation used by the asyncio event loop:
166
167.. function:: get_child_watcher()
168
169   Return the current child watcher for the current policy.
170
171   .. deprecated:: 3.12
172
173.. function:: set_child_watcher(watcher)
174
175   Set the current child watcher to *watcher* for the current
176   policy.  *watcher* must implement methods defined in the
177   :class:`AbstractChildWatcher` base class.
178
179   .. deprecated:: 3.12
180
181.. note::
182   Third-party event loops implementations might not support
183   custom child watchers.  For such event loops, using
184   :func:`set_child_watcher` might be prohibited or have no effect.
185
186.. class:: AbstractChildWatcher
187
188   .. method:: add_child_handler(pid, callback, *args)
189
190      Register a new child handler.
191
192      Arrange for ``callback(pid, returncode, *args)`` to be called
193      when a process with PID equal to *pid* terminates.  Specifying
194      another callback for the same process replaces the previous
195      handler.
196
197      The *callback* callable must be thread-safe.
198
199   .. method:: remove_child_handler(pid)
200
201      Removes the handler for process with PID equal to *pid*.
202
203      The function returns ``True`` if the handler was successfully
204      removed, ``False`` if there was nothing to remove.
205
206   .. method:: attach_loop(loop)
207
208      Attach the watcher to an event loop.
209
210      If the watcher was previously attached to an event loop, then
211      it is first detached before attaching to the new loop.
212
213      Note: loop may be ``None``.
214
215   .. method:: is_active()
216
217      Return ``True`` if the watcher is ready to use.
218
219      Spawning a subprocess with *inactive* current child watcher raises
220      :exc:`RuntimeError`.
221
222      .. versionadded:: 3.8
223
224   .. method:: close()
225
226      Close the watcher.
227
228      This method has to be called to ensure that underlying
229      resources are cleaned-up.
230
231   .. deprecated:: 3.12
232
233
234.. class:: ThreadedChildWatcher
235
236   This implementation starts a new waiting thread for every subprocess spawn.
237
238   It works reliably even when the asyncio event loop is run in a non-main OS thread.
239
240   There is no noticeable overhead when handling a big number of children (*O*\ (1) each
241   time a child terminates), but starting a thread per process requires extra memory.
242
243   This watcher is used by default.
244
245   .. versionadded:: 3.8
246
247.. class:: MultiLoopChildWatcher
248
249   This implementation registers a :py:data:`SIGCHLD` signal handler on
250   instantiation. That can break third-party code that installs a custom handler for
251   :py:data:`SIGCHLD` signal.
252
253   The watcher avoids disrupting other code spawning processes
254   by polling every process explicitly on a :py:data:`SIGCHLD` signal.
255
256   There is no limitation for running subprocesses from different threads once the
257   watcher is installed.
258
259   The solution is safe but it has a significant overhead when
260   handling a big number of processes (*O*\ (*n*) each time a
261   :py:data:`SIGCHLD` is received).
262
263   .. versionadded:: 3.8
264
265   .. deprecated:: 3.12
266
267.. class:: SafeChildWatcher
268
269   This implementation uses active event loop from the main thread to handle
270   :py:data:`SIGCHLD` signal. If the main thread has no running event loop another
271   thread cannot spawn a subprocess (:exc:`RuntimeError` is raised).
272
273   The watcher avoids disrupting other code spawning processes
274   by polling every process explicitly on a :py:data:`SIGCHLD` signal.
275
276   This solution is as safe as :class:`MultiLoopChildWatcher` and has the same *O*\ (*n*)
277   complexity but requires a running event loop in the main thread to work.
278
279   .. deprecated:: 3.12
280
281.. class:: FastChildWatcher
282
283   This implementation reaps every terminated processes by calling
284   ``os.waitpid(-1)`` directly, possibly breaking other code spawning
285   processes and waiting for their termination.
286
287   There is no noticeable overhead when handling a big number of
288   children (*O*\ (1) each time a child terminates).
289
290   This solution requires a running event loop in the main thread to work, as
291   :class:`SafeChildWatcher`.
292
293   .. deprecated:: 3.12
294
295.. class:: PidfdChildWatcher
296
297   This implementation polls process file descriptors (pidfds) to await child
298   process termination. In some respects, :class:`PidfdChildWatcher` is a
299   "Goldilocks" child watcher implementation. It doesn't require signals or
300   threads, doesn't interfere with any processes launched outside the event
301   loop, and scales linearly with the number of subprocesses launched by the
302   event loop. The main disadvantage is that pidfds are specific to Linux, and
303   only work on recent (5.3+) kernels.
304
305   .. versionadded:: 3.9
306
307
308.. _asyncio-custom-policies:
309
310Custom Policies
311===============
312
313To implement a new event loop policy, it is recommended to subclass
314:class:`DefaultEventLoopPolicy` and override the methods for which
315custom behavior is wanted, e.g.::
316
317    class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
318
319        def get_event_loop(self):
320            """Get the event loop.
321
322            This may be None or an instance of EventLoop.
323            """
324            loop = super().get_event_loop()
325            # Do something with loop ...
326            return loop
327
328    asyncio.set_event_loop_policy(MyEventLoopPolicy())
329