blob: 7bb1c1587b7a7480449fed48f52d2a18adcc3923 [file] [log] [blame]
Yury Selivanov7c7605f2018-09-11 09:54:40 -07001.. currentmodule:: asyncio
2
3
4.. _asyncio-policies:
5
6========
7Policies
8========
9
10An event loop policy, a global per-process object, controls
11management of the event loop. Each event loop has a default
12policy, which can be changed and customized using the API.
13
14A policy defines the notion of context and manages a
15separate event loop per context. The default policy
16defines context to be the current thread.
17
18By using a custom event loop policy, the behavior of
19:func:`get_event_loop`, :func:`set_event_loop`, and
20:func:`new_event_loop` functions can be customized.
21
22Policy objects should implement the APIs defined
23in the abstract base class :class:`AbstractEventLoopPolicy`.
24
25
26Access the Policy
27=================
28
29The following functions can be used to get and set the policy
30for the current process:
31
32.. function:: get_event_loop_policy()
33
34 Return the current process-wide policy.
35
36.. function:: set_event_loop_policy(policy)
37
38 Set the current process-wide policy to *policy*.
39
40 If *policy* is set to ``None``, the default policy is restored.
41
42
43Policy Objects
44==============
45
46The abstract event loop policy base class is defined as follows:
47
48.. class:: AbstractEventLoopPolicy
49
50 An abstract base class for asyncio policies.
51
52 .. method:: get_event_loop()
53
54 Get the event loop for the current context.
55
56 Return an event loop object implementing the
57 :class:`AbstractEventLoop` interface.
58
59 This method should never return ``None``.
60
61 .. versionchanged:: 3.6
62
63 .. method:: set_event_loop(loop)
64
65 Set the event loop for the current context to *loop*.
66
67 .. method:: new_event_loop()
68
69 Create and return a new event loop object.
70
71 This method should never return ``None``.
72
73 .. method:: get_child_watcher()
74
75 Get a child process watcher object.
76
77 Return a watcher object implementing the
78 :class:`AbstractChildWatcher` interface.
79
80 This function is Unix specific.
81
82 .. method:: set_child_watcher(watcher)
83
84 Get the current child process watcher to *watcher*.
85
86 This function is Unix specific.
87
88
89asyncio ships with the following built-in policies:
90
91
92.. class:: DefaultEventLoopPolicy
93
94 The default asyncio policy. Uses :class:`SelectorEventLoop`
95 on both Unix and Windows platforms.
96
97 There is no need to install the default policy manually; asyncio
98 is configured to use it automatically.
99
100
101.. class:: WindowsProactorEventLoopPolicy
102
103 An alternative event loop policy that uses the
104 :class:`ProactorEventLoop` event loop implementation.
105
106 Availability: Windows.
107
108
109Process Watchers
110================
111
112A process watcher allows customization of how an event loop monitors
113child processes on Unix. Specifically, the event loop needs to know
114when a child process has finished its execution.
115
116In asyncio, child processes are created with
117:func:`create_subprocess_exec` and :meth:`loop.subprocess_exec`
118functions.
119
120asyncio defines an abstract base class :class:`AbstractChildWatcher`
121that child watchers should implement, and has two different
122implementations: :class:`SafeChildWatcher` (configured to be used
123by default) and :class:`FastChildWatcher`.
124
125See also the :ref:`Subprocess and Threads <asyncio-subprocess-threads>`
126section.
127
128The following two functions can be used to customize the watcher
129implementation used by the asyncio event loop:
130
131.. function:: get_child_watcher()
132
133 Return the current child watcher for the current policy.
134
135.. function:: set_child_watcher(watcher)
136
137 Set the current child watcher to *watcher* for the current
138 policy. *watcher* must implement methods defined in the
139 :class:`AbstractChildWatcher` base class.
140
141.. note::
142 Third-party event loops implementations might not support
143 custom child watchers. For such event loops, using
144 :func:`set_child_watcher` might have no effect or even can
145 be prohibited.
146
147.. class:: AbstractChildWatcher
148
149 .. method:: add_child_handler(pid, callback, \*args)
150
151 Register a new child handler.
152
153 Arrange for ``callback(pid, returncode, *args)`` to be called
154 when a process with PID equal to *pid* terminates. Specifying
155 another callback for the same process replaces the previous
156 handler.
157
158 *callback* callable must be thread-safe.
159
160 .. method:: remove_child_handler(pid)
161
162 Removes the handler for process with PID equal to *pid*.
163
164 The function returns ``True`` if the handler was successfully
165 removed, ``False`` if there was nothing to remove.
166
167 .. method:: attach_loop(loop)
168
169 Attach the watcher to an event loop.
170
171 If the watcher was previously attached to an event loop, then
172 it is first detached before attaching to the new loop.
173
174 Note: loop may be ``None``.
175
176 .. method:: close()
177
178 Close the watcher.
179
180 This method has to be called to ensure that underlying
181 resources are cleaned-up.
182
183.. class:: SafeChildWatcher
184
185 This implementation avoids disrupting other code spawning processes
186 by polling every process explicitly on a :py:data:`SIGCHLD` signal.
187
188 This is a safe solution but it has a significant overhead when
189 handling a big number of processes (*O(n)* each time a
190 :py:data:`SIGCHLD` is received).
191
192 asyncio uses this implementation by default.
193
194.. class:: FastChildWatcher
195
196 This implementation reaps every terminated processes by calling
197 ``os.waitpid(-1)`` directly, possibly breaking other code spawning
198 processes and waiting for their termination.
199
200 There is no noticeable overhead when handling a big number of
201 children (*O(1)* each time a child terminates).
202
203
204Custom Policies
205===============
206
207To implement a new event loop policy, it is recommended to subclass
208:class:`DefaultEventLoopPolicy` and override the methods for which
209custom behavior is wanted, e.g.::
210
211 class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
212
213 def get_event_loop(self):
214 """Get the event loop.
215
216 This may be None or an instance of EventLoop.
217 """
218 loop = super().get_event_loop()
219 # Do something with loop ...
220 return loop
221
222 asyncio.set_event_loop_policy(MyEventLoopPolicy())