Kostis4444
Kostis4444

Reputation: 45

Asyncio HTTP requests without blocking main thread

I have a main thread which always needs to be available to read keyboard keypress input.

On each keypress I have to run 4 functions such as displaying, saving to a file, and making an HTTP request etc.

The keypresses can happen quicker than executing the 4 functions.

My logic is the following, but cannot see how I can keep key_press() always running, since I have to await the functions to finish at some point.

async def main():
  async with aiohttp.ClientSession() as client:
  while True:
    pressed_key = key_press() 
    if pressed_key != "":
        f1 = asyncio.create_task(do_something1())
        f2 = asyncio.create_task(do_something2())
        f3 = asyncio.create_task(do_something3())
        f4 = asyncio.create_task(send_to_API())
        
    await f1,f2,f3,send_to_API

asyncio.run(main())
    

Should I try some additional logic, with more loops after calling the asyncio.tasks recursively? Or should I look towards multi-threading, having a thread active running key_press() and the asynchronous calls elsewhere? Any ideas, or hints going towards a good direction?

Upvotes: 0

Views: 1504

Answers (1)

Artiom  Kozyrev
Artiom Kozyrev

Reputation: 3856

If you are trying to simulate USB data stream with the help of input (key_press function in your example), you have to use multithreading module, since input is a blocking function and it will stop asyncio loop work in the thread. To combine asyncio with input function you'll have to use another thread, please find the following example:

import asyncio
import threading


async def do_work(i):
    """take input key and do some work with the input"""
    await asyncio.sleep(5)
    print(i)


async def main_thread_loop_work(_key):
    """simulate multiple tasks caused by key input"""
    t1 = asyncio.create_task(do_work(_key))
    t2 = asyncio.create_task(do_work(_key))
    t3 = asyncio.create_task(do_work(_key))
    await t1
    await t2
    await t3


def thead_worker(_key):
    """target function for another thread"""
    asyncio.run(main_thread_loop_work(_key))


if __name__ == '__main__':
    while True:
        some_key = input("Please provide any key: ")
        th = threading.Thread(target=thead_worker, args=(some_key, ))
        th.start()

Upvotes: 3

Related Questions