Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asyncio run or run_until_complete

I am using asyncio for an application in a very basic way. Checking most tutorials around the internet (and even the official docs), I see that they use the get_event_loop() and loop.run_until_complete():

import asyncio

async def say(what, when):
    await asyncio.sleep(when)
    print(what)

loop = asyncio.get_event_loop()
loop.run_until_complete(say('hello world', 1))
loop.close()

But in the Python 3.7 docs, we can read:

Application developers should typically use the high-level asyncio functions, such as asyncio.run(), and should rarely need to reference the loop object or call its methods. This section is intended mostly for authors of lower-level code, libraries, and frameworks, who need finer control over the event loop behavior.

I found it much cleaner and easier to use, but it only works for Python 3.7+. So here I would have to make a choice, whether to use Python 3.7+ and run() or make it compatible with Python 3.6 and use the event loop. How would you manage this? Is there a simple way to make it backwards compatible with Python 3.6? Should I check Python version first and use either one way or another based on that, until Python 3.7 becomes a common version?

like image 372
makeMonday Avatar asked Apr 09 '19 10:04

makeMonday


People also ask

What is Asyncio run?

asyncio. run(main()) asyncio is a library to write concurrent code using the async/await syntax. asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc.

How many times should Asyncio run () be called?

It should be used as a main entry point for asyncio programs, and should ideally only be called once. New in version 3.7.

Does run until complete block?

run_forever() to run multiple co-routines concurrently. run_until_complete doesn't block anything. The difference between it and run_forever is that the loop pauses at the completion of the coroutine. The only time it will block is if your coroutine never awaits.

How do I stop Asyncio from running?

Run an asyncio Event Loop run_until_complete(<some Future object>) – this function runs a given Future object, usually a coroutine defined by the async / await pattern, until it's complete. run_forever() – this function runs the loop forever. stop() – the stop function stops a running loop.


1 Answers

Is there a simple way to make [code making use of asyncio.run] backwards compatible with Python 3.6?

You can implement a simple substitute for asyncio.run and call it on older Python versions:

import asyncio, sys, types

def run(coro):
    if sys.version_info >= (3, 7):
        return asyncio.run(coro)

    # Emulate asyncio.run() on older versions

    # asyncio.run() requires a coroutine, so require it here as well
    if not isinstance(coro, types.CoroutineType):
        raise TypeError("run() requires a coroutine object")

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        return loop.run_until_complete(coro)
    finally:
        loop.close()
        asyncio.set_event_loop(None)

The advantage of this approach over just using loop.run_until_complete() is that you're executing your code under the semantics close to those of the new asyncio.run, even on older Python versions. (For example, you will always run on a freshly created event loop.) Dropping support for pre-3.7 Python will be as easy as removing the run shim and calling asyncio.run directly.

like image 60
user4815162342 Avatar answered Sep 18 '22 15:09

user4815162342