Skip to content

Instantly share code, notes, and snippets.

@stuaxo
Last active July 13, 2018 12:24
Show Gist options
  • Save stuaxo/9308767 to your computer and use it in GitHub Desktop.
Save stuaxo/9308767 to your computer and use it in GitHub Desktop.
"""
Interuptible cmd.Cmd.
This is useful if you need a long running thread like a GUI event loop.
The trick is to run the cmd.Cmd shell in the main thread, and your main
loop in another background thread.
The app needs to be able to quit from both the main thread and main loop.
If quitting from the mainloop (other thread), it sends SIGINT, which
will interrupts the shell with KeybaordInterrupt.
If quitting from the shell (main thread), then the a variable in the
mainloop is set which then quits.
"""
import cmd
import os
import time
import sys
import signal
import threading
run_app_loop = True
def mainloop():
global run_app_loop
# This could run your main GUI thread. or other long running code
iterations = 0
while run_app_loop:
time.sleep(1) # Simulate doing something.
# On the 7th run simulate a quit triggered in this thread
iterations += 1
if iterations == 7:
print '\nSimulating quit event'
run_app_loop = False
print '\nQuit app thread.'
os.kill(os.getpid(), signal.SIGINT) # Tell the other thread to quit with SIGINT
class TestCmd(cmd.Cmd):
def do_quit(self, line):
return self.do_EOF("")
def do_EOF(self, line):
global run_app_loop
print 'Telling other thread to quit.'
run_app_loop = False
return True
t = threading.Thread(target=mainloop)
t.start()
try:
print 'Will quit automatically in 8 seconds, interrupting cmd.Cmd'
shell = TestCmd()
shell.do_help("")
shell.cmdloop()
run_app_loop = False
t.join()
except KeyboardInterrupt:
if run_app_loop:
raise
else:
print '\nBye'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment