asyncio run or run_until_complete

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.

Leave a Comment