[Async-sig] Adding asyncio.run() function in Python 3.6

Nathaniel Smith njs at pobox.com
Wed Nov 16 15:35:08 EST 2016


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" <yselivanov at 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 at python.org
> https://mail.python.org/mailman/listinfo/async-sig
> Code of Conduct: https://www.python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/async-sig/attachments/20161116/f088cbcc/attachment.html>


More information about the Async-sig mailing list