quixadhal

Threading PITA

Jul 30th, 2023
979
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.02 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import readline
  3. import asyncio
  4. import threading
  5. from threading import Thread
  6. import sys
  7. #from asyncio.subprocess import PIPE, STDOUT
  8.  
  9. streaming_queue = asyncio.Queue()
  10.  
  11. def stderr_print(*args, **kwargs):
  12.     print(*args, file=sys.stderr, **kwargs)
  13.  
  14.  
  15. async def handle_console_input(loop, running):
  16.     while running.is_set():
  17.         chunk = await streaming_queue.get()
  18.         if chunk == 'quit':
  19.             stderr_print("quit detected!")
  20.             running.clear()
  21.         stderr_print("got chunk: \"%s\"" % chunk)
  22.         if not running.is_set():
  23.             print("clear handle_console_input")
  24.  
  25.  
  26. def command_console(loop, running):
  27.     try:
  28.         loop.run_until_complete(handle_console_input(loop, running))
  29.         stderr_print("completed")
  30.         running.clear()
  31.         if not running.is_set():
  32.             print("clear_command_console")
  33.         exit
  34.     except asyncio.CancelledError:
  35.         loop.close()
  36.         stderr_print("loop closed")
  37.         running.clear()
  38.         if not running.is_set():
  39.             print("clear_command_console exception")
  40.         exit
  41.  
  42. def queue_console_input(chunk):
  43.     streaming_queue.put_nowait(chunk)
  44.  
  45.  
  46. def shutdown_threads():
  47.     for task in asyncio.all_tasks():
  48.         task.cancel()
  49.  
  50.  
  51. if __name__ == "__main__":
  52.     loop = asyncio.get_event_loop()
  53.     thread_running = threading.Event()
  54.     thread_running.set()
  55.     event_thread = Thread(target=command_console, args=(loop,thread_running))
  56.     event_thread.start()
  57.     try:
  58.         while thread_running.is_set():
  59.             if not thread_running.is_set():
  60.                 print("clear main")
  61.             else:
  62.                 print("set main")
  63.             chunk = input('console> ')
  64.             loop.call_soon_threadsafe(queue_console_input, chunk)
  65.         if not thread_running.is_set():
  66.             print("clear main outside")
  67.         stderr_print("cancelling all tasks")
  68.         loop.call_soon_threadsafe(shutdown_threads)
  69.         stderr_print("joining thread")
  70.         event_thread.join()
  71.         stderr_print("done")
  72.     except KeyboardInterrupt:
  73.         stderr_print("Got INTERRUPT!")
  74.         stderr_print("cancelling all tasks")
  75.         loop.call_soon_threadsafe(shutdown_threads)
  76.         stderr_print("joining thread")
  77.         event_thread.join()
  78.         stderr_print("done")
  79.  
  80. # wiley@lenin:~/WileyP$ ./readline_example.py
  81. # set main
  82. # console> foo
  83. # set main
  84. # console> got chunk: "foo"
  85. # bar
  86. # set main
  87. # console> got chunk: "bar"
  88. # quit
  89. # set main
  90. # console> quit detected!
  91. # got chunk: "quit"
  92. # clear handle_console_input
  93. # completed
  94. # clear_command_console
  95. #
  96. # clear main outside
  97. # cancelling all tasks
  98. # joining thread
  99. # done
  100.  
  101. # From what I can tell, the above code is NOT calling input() an extra time, yet for some reason we
  102. # do not progress past the while loop until I hit return again.  So, despite the loop.call_soon calling
  103. # a function that says not to wait, it still seems to be waiting for the (now dead) loop to empty the
  104. # message queue???
  105.  
Advertisement
Add Comment
Please, Sign In to add comment