What's the use case for the async generator version? Could the yield be replaced by 'await loop.shutting_down()'?
On Nov 16, 2016 10:12 AM, "Yury Selivanov" <yseliva...@gmail.com> wrote: > One of the remaining problems with the event loop in asyncio is > bootstrapping/finalizing asyncio programs. > > Currently, there are two different scenarios: > > [1] Running a coroutine: > > async def main(): > # your program > loop = asyncio.get_event_loop() > try: > loop.run_until_complete(main()) > finally: > loop.close() > > [2] Running a server: > > loop = asyncio.get_event_loop() > srv = loop.run_until_complete( > loop.create_server(…)) > try: > loop.run_forever() > finally: > try: > srv.close() > loop.run_until_complete(srv.wait_closed()) > finally: > loop.close() > > Both cases are *incomplete*: they don’t do correct finalization of > asynchronous generators. To do that we’ll need to add another 1-3 lines of > code (extra try-finally). > > This manual approach is really painful: > > * It makes bootstrapping asyncio code unnecessarily hard. > > * It makes the documentation hard to follow. And we can’t restructure the > docs to cover the loop only in the advanced section. > > * Most of the people will never know about `loop.shutdown_asyncgen` > coroutine. > > * We don’t have a place to add debug code to let people know that their > asyncio program didn’t clean all resources properly (a lot of unordered > warnings will be spit out instead). > > In https://github.com/python/asyncio/pull/465 I propose to add a new > function to asyncio in Python 3.6: asyncio.run(). > > The function can either accept a coroutine, which solves [1]: > > async def main(): > # your program > asyncio.run(main()) > > Or it can accept an asynchronous generator, which solves [2]: > > async def main(): > srv = await loop.create_server(…)) > try: > yield # let the loop run forever > finally: > srv.close() > await srv.wait_closed() > > asyncio.run(main()) > > asyncio.run() solves the following: > > * An easy way to start an asyncio program that properly takes care of loop > instantiation and finalization. > > * It looks much better in the docs. With asyncio.run people don’t need to > care about the loop at all, most probably will never use it. > > * Easier to experiment with asyncio in REPL. > > * The loop and asynchronous generators will be cleaned up properly. > > * We can add robust debug output to the function, listing the unclosed > tasks, servers, connections, asynchronous generators etc, helping people > with the cleanup logic. > > * Later, if we need to add more cleanup code to asyncio, we will have a > function to add the logic to. > > I feel that we should add this to asyncio. One of the arguments against > that, is that overloading asyncio.run to accept both coroutines and > asynchronous generators makes the API more complex. If that’s really the > case, we can add two functions: asyncio.run(coro) and > asyncio.run_forever(async_generator). > > Also take a look at https://github.com/python/asyncio/pull/465. > > Thanks, > Yury > _______________________________________________ > Async-sig mailing list > Async-sig@python.org > https://mail.python.org/mailman/listinfo/async-sig > Code of Conduct: https://www.python.org/psf/codeofconduct/
_______________________________________________ Async-sig mailing list Async-sig@python.org https://mail.python.org/mailman/listinfo/async-sig Code of Conduct: https://www.python.org/psf/codeofconduct/