I have a Python program running a (nested) loop which will run for a fairly long time, and I want the user to be able to pause and/or abort it with just pressing p and c, respectively.
I am running this in an IPython console, so I don't really have access to msvctr.getch
and I kinda want to keep it platform independent.
Obviously, input()
blocks, which is exactly what I do not want. So I tried threading, which works when used as intended, but when hitting CTRLC the thread does not stop. This is likely because any legitimate method to stop the thread (atexit, global variable or lambda stop_thread
) isn't executed because the thread blocks.
import threading
import queue
q = queue.SimpleQueue()
stop_thread = False
def handle_input(q, stopped):
s = ''
while not stopped():
s = input()
q.put(s)
thread = threading.Thread(target=handle_input,
args=[q, lambda: stop_thread])
thread.start()
for i in range(very_long_time):
#Do something time consuming
if not q.empty():
s = q.get_nowait()
if 'p' in s:
print('Paused...', end='\r')
s = s.replace('p', '')
while True:
if not q.empty():
s += q.get_nowait()
if 'p' in s or 'c' in s:
s = s.replace('p', '')
break
time.sleep(0.5)
if 'c' in s:
print('\rAborted training loop...' + ' '*50, end='\r')
s = s.replace('c', '')
stop_thread = True
# Another method of stopping the thread
# thread.__getattribute__('_tstate_lock').release()
# thread._stop()
# thread.join()
break
This works in principle, but breaks when interrupting.
The thread does not seem to stop, which poses a problem when running this again in the same console, because it does not even ask for user input then.
Additionally, this prints my 'c' or 'p' and a newline, which I can't get rid of, because IPython doesn't allow all ANSI escapes.
Is there a fix to my method, or even better, a cleaner alternative?