asyncio question

Frank Millman frank at chagford.com
Tue Nov 3 03:27:07 EST 2020


Hi all

My app runs an HTTP server using asyncio. A lot of the code dates back 
to Python 3.4, and I am trying to bring it up to date. There is one 
aspect I do not understand.

The 'old' way looks like this -

     import asyncio

     def main():
         loop = asyncio.get_event_loop()
         server = loop.run_until_complete(
             asyncio.start_server(handle_client, host, port))
         loop.run_forever()

     if __name__ == '__main__':
         main()

According to the docs, the preferred way is now like this -

     import asyncio

     async def main():
         loop = asyncio.get_running_loop()
         server = await asyncio.start_server(
              handle_client, host, port)
         async with server:
             server.serve_forever()

     if __name__ == '__main__':
         asyncio.run(main())

It works, and it does look neater. But I want to start some background 
tasks before starting the server, and cancel them on Ctrl+C.

Using the 'old' method, I can wrap 'loop.run_forever()' in a 
try/except/finally, check for KeyboardInterrupt, and run my cleanup in 
the 'finally' block.

Using the 'new' method, KeyboardInterrupt is not caught by 
'server.serve_forever()' but by 'asyncio.run()'. It is too late to do 
any cleanup at this point, as the loop has already been stopped.

Is it ok to stick to the 'old' method, or is there a better way to do this.

Thanks

Frank Millman



More information about the Python-list mailing list