blob: 42f936da468ee24c820e47175bf026048630f911 [file] [log] [blame]
Yury Selivanov512d7102018-09-17 19:35:30 -04001.. currentmodule:: asyncio
2
3
4.. _asyncio-policies:
5
6========
7Policies
8========
9
10An event loop policy is a global per-process object that controls
11the management of the event loop. Each event loop has a default
12policy, which can be changed and customized using the policy 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 :class:`AbstractEventLoopPolicy` abstract base class.
24
25
26Getting and Setting 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 the default policy 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 exited.
115
116In asyncio, child processes are created with
117:func:`create_subprocess_exec` and :meth:`loop.subprocess_exec`
118functions.
119
120asyncio defines the :class:`AbstractChildWatcher` abstract base class,
121which 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 child process 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 be prohibited or have no effect.
145
146.. class:: AbstractChildWatcher
147
148 .. method:: add_child_handler(pid, callback, \*args)
149
150 Register a new child handler.
151
152 Arrange for ``callback(pid, returncode, *args)`` to be called
153 when a process with PID equal to *pid* terminates. Specifying
154 another callback for the same process replaces the previous
155 handler.
156
157 The *callback* callable must be thread-safe.
158
159 .. method:: remove_child_handler(pid)
160
161 Removes the handler for process with PID equal to *pid*.
162
163 The function returns ``True`` if the handler was successfully
164 removed, ``False`` if there was nothing to remove.
165
166 .. method:: attach_loop(loop)
167
168 Attach the watcher to an event loop.
169
170 If the watcher was previously attached to an event loop, then
171 it is first detached before attaching to the new loop.
172
173 Note: loop may be ``None``.
174
175 .. method:: close()
176
177 Close the watcher.
178
179 This method has to be called to ensure that underlying
180 resources are cleaned-up.
181
182.. class:: SafeChildWatcher
183
184 This implementation avoids disrupting other code spawning processes
185 by polling every process explicitly on a :py:data:`SIGCHLD` signal.
186
187 This is a safe solution but it has a significant overhead when
188 handling a big number of processes (*O(n)* each time a
189 :py:data:`SIGCHLD` is received).
190
191 asyncio uses this safe implementation by default.
192
193.. class:: FastChildWatcher
194
195 This implementation reaps every terminated processes by calling
196 ``os.waitpid(-1)`` directly, possibly breaking other code spawning
197 processes and waiting for their termination.
198
199 There is no noticeable overhead when handling a big number of
200 children (*O(1)* each time a child terminates).
201
202
203Custom Policies
204===============
205
206To implement a new event loop policy, it is recommended to subclass
207:class:`DefaultEventLoopPolicy` and override the methods for which
208custom behavior is wanted, e.g.::
209
210 class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
211
212 def get_event_loop(self):
213 """Get the event loop.
214
215 This may be None or an instance of EventLoop.
216 """
217 loop = super().get_event_loop()
218 # Do something with loop ...
219 return loop
220
221 asyncio.set_event_loop_policy(MyEventLoopPolicy())