On Tue, Nov 3, 2020 at 3:27 AM Frank Millman <fr...@chagford.com> wrote:
> 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. > It's fine to stick with the older method in your case, as there's nothing inherently wrong with continuing to use it. `asyncio.run()` is largely a convenience function that takes care of some finalization/cleanup steps that are often forgotten (cancelling remaining tasks, closing event loop's default ThreadPoolExecutor, closing async generators, etc). If you want to use custom KeyboardInterrupt handling and still use asyncio.run(), you can either (a) use `loop.add_signal_handler()` or (b) make a slightly modified local version of `asyncio.run()` that has your desired KeyboardInterrupt behavior, based roughly on https://github.com/python/cpython/blob/master/Lib/asyncio/runners.py. However, using `loop.run_until_complete()` instead of `asyncio.run()` is also perfectly fine, especially in existing code that still works without issue. It just leaves the author with a bit more responsibility when it comes to resource finalization and dealing with the event loop in general (which can add some extra cognitive burden and room for error, particularly when dealing with multiple event loops or threads). But it's reasonably common to continue using `loop.run_until_complete()` in situations where the default `asyncio.run()` behavior isn't what you need/want, such as your case. -- https://mail.python.org/mailman/listinfo/python-list