python - What's the correct way to clean up after an interrupted event loop? -


i have event loop runs co-routines part of command line tool. user may interrupt tool usual ctrl + c, @ point want clean after interrupted event loop.

here's tried.

import asyncio   @asyncio.coroutine def shleepy_time(seconds):     print("shleeping {s} seconds...".format(s=seconds))     yield asyncio.sleep(seconds)   if __name__ == '__main__':     loop = asyncio.get_event_loop()      # side note: apparently, async() deprecated in 3.4.4.     # see: https://docs.python.org/3.4/library/asyncio-task.html#asyncio.async     tasks = [         asyncio.async(shleepy_time(seconds=5)),         asyncio.async(shleepy_time(seconds=10))     ]      try:         loop.run_until_complete(asyncio.gather(*tasks))     except keyboardinterrupt e:         print("caught keyboard interrupt. canceling tasks...")          # doesn't seem correct solution.         t in tasks:             t.cancel()     finally:         loop.close() 

running , hitting ctrl + c yields:

$ python3 asyncio-keyboardinterrupt-example.py  shleeping 5 seconds... shleeping 10 seconds... ^ccaught keyboard interrupt. canceling tasks... task destroyed pending! task: <task pending coro=<shleepy_time() running @ asyncio-keyboardinterrupt-example.py:7> wait_for=<future cancelled> cb=[gather.<locals>._done_callback(1)() @ /usr/local/cellar/python3/3.4.3/frameworks/python.framework/versions/3.4/lib/python3.4/asyncio/tasks.py:587]> task destroyed pending! task: <task pending coro=<shleepy_time() running @ asyncio-keyboardinterrupt-example.py:7> wait_for=<future cancelled> cb=[gather.<locals>._done_callback(0)() @ /usr/local/cellar/python3/3.4.3/frameworks/python.framework/versions/3.4/lib/python3.4/asyncio/tasks.py:587]> 

clearly, didn't clean correctly. thought perhaps calling cancel() on tasks way it.

what's correct way clean after interrupted event loop?

when ctrl+c, event loop gets stopped, calls t.cancel() don't take effect. tasks cancelled, need start loop again.

here's how can handle it:

import asyncio  @asyncio.coroutine def shleepy_time(seconds):     print("shleeping {s} seconds...".format(s=seconds))     yield asyncio.sleep(seconds)   if __name__ == '__main__':     loop = asyncio.get_event_loop()      # side note: apparently, async() deprecated in 3.4.4.     # see: https://docs.python.org/3.4/library/asyncio-task.html#asyncio.async     tasks = asyncio.gather(         asyncio.async(shleepy_time(seconds=5)),         asyncio.async(shleepy_time(seconds=10))     )      try:         loop.run_until_complete(tasks)     except keyboardinterrupt e:         print("caught keyboard interrupt. canceling tasks...")         tasks.cancel()         loop.run_forever()         tasks.exception()     finally:         loop.close() 

once catch keyboardinterrupt, call tasks.cancel() , start loop again. run_forever exit tasks gets cancelled (note cancelling future returned asyncio.gather cancels futures inside of it), because interrupted loop.run_until_complete call added done_callback tasks stops loop. so, when cancel tasks, callback fires, , loop stops. @ point call tasks.exception, avoid getting warning not fetching exception _gatheringfuture.


Comments

Popular posts from this blog

javascript - gulp-nodemon - nodejs restart after file change - Error: listen EADDRINUSE events.js:85 -

Fatal Python error: Py_Initialize: unable to load the file system codec. ImportError: No module named 'encodings' -

javascript - oscilloscope of speaker input stops rendering after a few seconds -