asyncio print something while waiting for user input

Viewed 1716

I have a simple script, I want the user to be able to input something whenever he wants, but I want to also print something out in the meantine, this is my code:

import asyncio

async def user_input():
   while True:
        content = input('> ')


async def print_something():
    await asyncio.sleep(10)
    print('something')


async def main():
    tasks = [user_input(), print_something()]
    await asyncio.gather(*tasks)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

It lets me input, but it doesn't print something, how can I achieve that?

2 Answers

input is a blocking function and cannot be used with inside coroutines straightforwardly. But you could start it in a separate thread by means of run_in_executor:

import asyncio


async def user_input():
    while True:
        loop = asyncio.get_event_loop()
        content = await loop.run_in_executor(None, input, "> ")
        print(content)


async def print_something():
    await asyncio.sleep(5)
    print('something')


async def main():
    tasks = [user_input(), print_something()]
    await asyncio.gather(*tasks)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Update: Also you can use aioconsole lib, which provides asyncio-based console functions:

from aioconsole import ainput

async def user_input():
    while True:
        content = await ainput(">")
        print(content)

The short answer is async cannot do what you are wanting. While you did declare your functions as async the python function input is not async, it is a blocking function. So it will block the event loop and nothing else will run.

I answered a question awhile back that kinda explains how async works in python. I'll link it. But in order to do what you want you need to use threads not async. https://stackoverflow.com/a/63237798/9270488

If you want to use threads with async then look into ThreadExecutor

Related