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

Reply via email to