@@ -77,12 +77,12 @@ class StopAsyncIteration(Exception):
7777
7878class EventLoopPolicy (asyncio .DefaultEventLoopPolicy ):
7979 """
80- Creates and sets up a new asyncio event loop that is capable of spawning
81- and watching subprocesses.
80+ An event loop policy that ensures the event loop is capable of spawning
81+ and watching subprocesses, even when not running in the main thread .
8282
83- Unix: Uses relatively slow polling to watch child processes, when not
84- running on the main thread. This only affects detection of process
85- termination, not communication.
83+ Unix: Child watchers are thread local. Uses relatively slow polling to
84+ watch child processes, when not running on the main thread. This only
85+ affects detection of process termination, not communication.
8686 """
8787 class _ThreadLocal (threading .local ):
8888 _watcher = None
@@ -128,42 +128,40 @@ def _poll(self):
128128 def set_child_watcher (self , watcher ):
129129 if sys .platform == "win32" or threading .current_thread () == threading .main_thread ():
130130 return super ().set_child_watcher (watcher )
131- else :
132- assert watcher is None or isinstance (watcher , asyncio .AbstractChildWatcher )
133131
134- if self ._thread_local ._watcher :
135- self ._thread_local ._watcher .close ()
136- self ._thread_local ._watcher = watcher
132+ assert watcher is None or isinstance (watcher , asyncio .AbstractChildWatcher )
133+
134+ if self ._thread_local ._watcher :
135+ self ._thread_local ._watcher .close ()
136+ self ._thread_local ._watcher = watcher
137137
138138 def new_event_loop (self ):
139139 return asyncio .ProactorEventLoop () if sys .platform == "win32" else asyncio .SelectorEventLoop ()
140140
141- def get_event_loop (self ):
142- print ("GET EVENT LOOP" )
143- return super ().get_event_loop ()
144-
145141 def set_event_loop (self , loop ):
146- print ("SET EVENT LOOP" , threading .current_thread ())
147142 super ().set_event_loop (loop )
148143
149144 if sys .platform != "win32" and threading .current_thread () != threading .main_thread ():
150- print ("ATTACHING EVENT LOOP" )
151145 self .get_child_watcher ().attach_loop (loop )
152146
153147
154- def run_in_background (coroutine ):
148+ def run_in_background (coroutine , _policy_lock = threading . Lock () ):
155149 """
156150 Runs ``coroutine(future)`` in a new event loop on a background thread.
157151
158152 Blocks and returns the *future* result as soon as it is resolved.
159153 The coroutine and all remaining tasks continue running in the background
160154 until it is complete.
155+
156+ Note: This installs an event loop policy for the entire process.
161157 """
162158 assert asyncio .iscoroutinefunction (coroutine )
163159
164160 future = concurrent .futures .Future ()
165161
166- asyncio .set_event_loop_policy (EventLoopPolicy ())
162+ with _policy_lock :
163+ if not isinstance (asyncio .get_event_loop_policy (), EventLoopPolicy ):
164+ asyncio .set_event_loop_policy (EventLoopPolicy ())
167165
168166 def background ():
169167 loop = asyncio .new_event_loop ()
0 commit comments