'Asyncio code finishes in Python3.8/9, but not Python 3.6.1 (reproducible example included)

The code below is a reproducible example of code I need to backport to 3.6.1 (because that is what I can use on the university cluster).

This is code that runs async code in a different thread so that the REPL is not affected.

If I run it in the IPython3.8/3.9 REPLs, the coroutine finishes. If I run it in 3.6.1 it only runs until await proc.communicate().

However, if I add a asyncio.get_event_loop().run_until_complete(asyncio.gather(dummy())) the finish messages show up.

Remember that this code is meant to be used from the REPL where I want processing to be done async in another thread so my REPL is always responsive.

import asyncio
import atexit

from datetime import datetime
from threading import Thread

asyncio.get_child_watcher()
asyncio.get_event_loop()

def _start_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

background_loop = asyncio.new_event_loop()
thread = Thread(target=_start_loop, args=(background_loop,))
thread.daemon = True
thread.start()

async def dummy():
    await asyncio.sleep(0.001)

def run_background_task(coroutine, loop):
    return asyncio.run_coroutine_threadsafe(coroutine, loop)

async def test_task(whence):
    now = datetime.now()

    current_time = now.strftime("%H:%M:%S")

    print(f"started {whence} @ {current_time}")
    proc = await asyncio.subprocess.create_subprocess_shell(f"touch {whence}; echo hi; sleep 1; echo ho",
                                                           stderr=asyncio.subprocess.PIPE,
                                                           stdout=asyncio.subprocess.PIPE)
    (stdout, stderr) = await proc.communicate()
    stdout, stderr = stdout.decode(), stderr.decode()
    print(f"stdout: {stdout}")
    print(f"stderr: {stderr}")

    now = datetime.now()

    current_time = now.strftime("%H:%M:%S")

    print(f"finished {whence} @ {current_time}")

    return proc, stdout, stderr

background_task = run_background_task(
    test_task("background_task"), background_loop
)

Is there a reason why? In Python 3.6.1 it only prints the start message, none of the following ones.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source