Programmatically exit the REPL
Matthew Fitzgibbons
elessar at nienna.org
Tue Aug 26 16:47:45 EDT 2008
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
More information about the Python-list
mailing list