Issue
I'm trying to build a script that runs asynchronously while having a start/stop mechanism based on user input from stdin.
I created two threads, one for the asynchronous work and one for reading from stdin. My idea is that the program runs until the user types "stop" in stdin, and the asynchronous tasks wait until the user types "start" in stdin.
Here is my current code:
class DataManager(metaclass=Singleton):
def __init__(self):
self.flag = threading.Event()
self.flag.set()
# Thread for reading user input
self.pool_thread = threading.Thread(target=self.__pool_input())
self.pool_thread.daemon = True
self.pool_thread.start()
# Method to create thread for asynchronous tasks
def start(self):
if self.flag.is_set():
self.flag.clear()
self.main_thread = threading.Thread(target=self.__main_wrapper)
self.main_thread.start()
# Method for reading user stdin
def __pool_input(self):
val = input()
if val == "stop":
self.stop()
elif val == "start":
self.start()
# Wrapper method to start the event loop and call async context
def __main_wrapper(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.__main())
loop.close()
# Main async loop
async def __main(self):
while not self.flag.is_set():
# Run async stuff
# ...
print('Thread is running')
await asyncio.sleep(5)
# Stop the main async loop on user command
def stop(self):
if not self.flag.is_set():
self.flag.set()
if __name__ == "__main__":
data_manager = DataManager()
data_manager.start()
Expected behavior
- Async (main) thread runs on loop
- User types "stop" and async thread stops
- User types "start" and async loop runs again
Current behavior
- Async thread is blocked until user types on stdin
- Async thread starts running
- Stdin is blocked while async thread runs
Besides having to keep the __pool_input
thread active in some way (because once it reads the input once the thread ends and I never start it again) I don't know how to make the desired outcome work.
Solution
Your program doesn‘t work, because you are not passing __pool_input
as target
but calling it. Use
self.pool_thread = threading.Thread(target=self.__pool_input)
and I guess it should work. Once. As you said.
You can create an infinite loop in __pool_input()
the same way you did in __main_wrapper()
to read from stdin again.
That being said, I think you should change your design. The great thing about async code is that you don‘t need threads (for anything I/O) and threading is very hard. So best avoid them where you can. There was a similar question recently about async input
. Maybe you find something in there you like.
Answered By - thisisalsomypassword
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.