asyncio - how to stop loop?
Ian Kelly
ian.g.kelly at gmail.com
Wed Jun 11 09:56:40 EDT 2014
On Wed, Jun 11, 2014 at 1:19 AM, Frank Millman <frank at chagford.com> wrote:
> First attempt - same as before
>
> loop = asyncio.get_event_loop()
> threading.Thread(target=loop.run_forever).start()
> input('Press <enter> to stop')
> loop.stop()
> loop.close()
Each event loop is hosted by a specific thread. In this case you're
getting the event loop of the main thread and then trying to run it in
a separate thread, which is not a good idea. You can run an event
loop in a separate thread, but you should install a separate event
loop for that thread if you do (and then when you interact with the
loop, do so in a thread-safe manner -- see below).
> Second attempt - move the keyboard input to a separate thread
>
> def stop_loop():
> input('Press <enter> to stop')
> loop.stop()
> loop.close()
>
> loop = asyncio.get_event_loop()
> threading.Thread(target=stop_loop).start()
> loop.run_forever()
One issue here is that (like most event loop implementations) event
loops are not thread-safe. To make a call to the event loop across
threads, you should be using the call_soon_threadsafe method, e.g.
"loop.call_soon_threadsafe(loop.stop)". You'll also want to make sure
that the event loop has actually stopped before you call loop.close --
see below.
> Third attempt - get the loop to close itself (cannot use in practice, but
> see what happens)
>
> def stop_loop():
> loop.stop()
> loop.close()
>
> loop = asyncio.get_event_loop()
> loop.call_later(2, stop_loop)
> loop.run_forever()
I think what's happening here is that per the docs loop.close should
not be called while the loop is running. You've called loop.stop but
you're still inside a callback, which is a bit of a gray area. You
probably don't need to call loop.close at all, but if you want to do
so I suggest putting it after the run_forever call, so you can be
certain the loop has stopped when it's called.
Putting all that together, you should have something like this:
def stop_loop():
input('Press <enter> to stop')
loop.call_soon_threadsafe(loop.stop)
loop = asyncio.get_event_loop()
threading.Thread(target=stop_loop).start()
loop.run_forever()
loop.close() # optional
More information about the Python-list
mailing list