asyncio - how to stop loop?

Frank Millman frank at chagford.com
Wed Jun 11 03:19:04 EDT 2014


Hi all

I have a 'start.py' script that kicks off my program by starting a number of 
services.

For now, I stop it by allowing the user to press <enter>, after which I 
close down the services and stop the program. (For production I imagine it 
would be better to run it in the background and send it some kind of signal 
to terminate, but for testing this suffices.)

As one of the services is a 'listening' loop, which would normally prevent 
access to the keyboard, I start it in a separate thread. For example, when I 
was using cherrypy as the server, I had -

    server = cherrypy.wsgiserver.CherryPyWSGIServer((host, port), 
dispatcher)
    threading.Thread(target=server.start).start()
    input('Press <enter> to stop')
    server.stop()

Now I am playing with asyncio, but I cannot get it to behave the same.

Here are my attempts. I use python 3.4.1, and I tested on Windows and 
Linux - the results are different on each platform.

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()

Windows traceback -

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python34\lib\threading.py", line 920, in _bootstrap_inner
    self.run()
  File "C:\Python34\lib\threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Python34\lib\asyncio\base_events.py", line 184, in run_forever
    self._run_once()
  File "C:\Python34\lib\asyncio\base_events.py", line 795, in _run_once
    event_list = self._selector.select(timeout)
AttributeError: 'NoneType' object has no attribute 'select'

With Linux, it does not terminate. If I press Ctrl_C, I get this traceback 
(hope there are no typos) -

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/threading.py", line 1294, in _shutdown
    t.join()
  File "/usr/local/lib/python3.4/threading.py", line 1060, in join
    self._wait_for_tstate_lock()
  File "/usr/local/lib/python3.4/threading.py", line 1076, in 
_wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt


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()

With Windows, it works - the program closes cleanly.

With Linux, it does not terminate. If I press Ctrl_C, I get this traceback 
(hope there are no typos) -

Traceback (most recent call last):
  File "test_async.py", line 20, in <module>
    loop.run_forever()
  File "/usr/local/lib/python3.4/asyncio.base_events.py", line 184, in 
run_forever
    self._run_once()
  File "/usr/local/lib/python3.4/asyncio.base_events.py", line 795, in 
_run_once
    event_list = self._selector.select(timeout)
  File "/usr/local/lib/python3.4/asyncio.selectors.py", line 424, in select
    fd_event_list = self._epoll.poll(timeout, max_cv)
KeyboardInterrupt


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()

Both platforms show the same traceback, after two seconds -

Traceback (most recent call last):
  File "C:\Documents and Settings\frank\aib\aib_async\test_async.py", line 
29, in <module>
    loop.run_forever()
  File "C:\Python34\lib\asyncio\base_events.py", line 184, in run_forever
    self._run_once()
  File "C:\Python34\lib\asyncio\base_events.py", line 795, in _run_once
    event_list = self._selector.select(timeout)
AttributeError: 'NoneType' object has no attribute 'select'

Can anyone suggest a way to get the loop to stop cleanly?

Thanks

Frank Millman






More information about the Python-list mailing list