Matthew Fitzgibbons wrote:
I've got a pretty complex interactive command line program. Instead of
writing my own REPL, I'm using the Python interpreter (an infinitely
better solution). This program has two threads, a background thread and
the REPL thread. When you call quit() or sys.exit() in the REPL thread,
everything is perfectly happy. However, the background thread does some
long-running jobs, and I want it to have the ability to exit the program
when the job is complete. When I call quit() or sys.exit() from the
background thread, the REPL merrily continues on its way.
This is a very frustrating problem, so I'm hoping someone can shed some
light on it. Am I missing something simple? Or is this just impossible?
I don't see anything about breaking out of interact() in the code module
docs.
Here's a minimal example:
#!/usr/bin/env python -i
# You get the same behavior using code.interact()
import sys
import time
import threading
def end_the_program():
# works if you call it from the REPL thread,
# but not the background thread
print "called end_the_program()"
sys.exit()
# quit() # using quit() rather than sys.exit()
# results in identical behavior
keep_going = True
def runner():
while keep_going:
time.sleep(0.1)
end_the_program()
threading.Thread(target=runner).start()
# end example
Here's the console session (edited for clarity):
Desktop$ ./exit_repl.py
>>> keep_going = False
called end_the_program()
# notice we didn't exit here
>>> end_the_program()
called end_the_program()
# but we did exit here
Desktop$
-Matt
Here's a modified example that _almost_ works:
#!/usr/bin/env python
import code
import time
import threading
keep_going = True
def runner():
while keep_going:
time.sleep(0.1)
ic.push("quit()") # this will exit the InteractiveConsole loop!
threading.Thread(target=runner).start()
ic = code.InteractiveConsole(locals())
ic.interact("InteractiveConsole")
# end example
It uses code.InteractiveConsole instead of python -i. When you push
"quit()" to the InteractiveConsole, the loop exits, but the raw_input
call is still blocking. Argh!
Console session:
Desktop$ ./exit_repl.py && echo done
InteractiveConsole
>>> keep_going = False
>>> <hit enter one more time...>
done
Desktop$
Does anyone know how to make raw_input think it has gotten input?
-Matt
--
http://mail.python.org/mailman/listinfo/python-list