Programmatically exit the REPL

  • Thread starter Matthew Fitzgibbons
  • Start date
M

Matthew Fitzgibbons

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.pycalled end_the_program()
# notice we didn't exit herecalled end_the_program()
# but we did exit here
Desktop$


-Matt
 
A

Alexander Schmolck

Without reading your post properly or having tried to do the same thing
myself: I think you might want to have a look at ipython; it gives a better
REPL and "embedding ipython" should give you plenty of hits as well.

Matthew Fitzgibbons said:
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
called end_the_program()
# notice we didn't exit here
called end_the_program()
# but we did exit here
Desktop$


-Matt

--
 
M

Matthew Fitzgibbons

Alexander said:
Without reading your post properly or having tried to do the same thing
myself: I think you might want to have a look at ipython; it gives a better
REPL and "embedding ipython" should give you plenty of hits as well.

Thanks for the tip; I hadn't heard of ipython before. I will certainly
check it out. However, if anyone knows how to break out of the
interactive interpreter from another thread, I'd still very much like to
hear about it. :)

-Matt
 
M

Matthew Fitzgibbons

Almar said:
Hi,

If you insist on writing your own shell, you can also consider running
the commands in another python process.
I took the source code of Pype as an example, which uses a wx.Process.
I've tried the subprocess module as well, but could not get it to work.

Almar

2008/8/26 Matthew Fitzgibbons <[email protected]
<mailto:[email protected]>>

Alexander Schmolck wrote:

Without reading your post properly or having tried to do the
same thing
myself: I think you might want to have a look at ipython; it
gives a better
REPL and "embedding ipython" should give you plenty of hits as well.


Thanks for the tip; I hadn't heard of ipython before. I will
certainly check it out. However, if anyone knows how to break out of
the interactive interpreter from another thread, I'd still very much
like to hear about it. :)


-Matt

The whole point is that I *don't* want to write my own shell, I want to
use the Python interactive shell (iPython, while very neat, is overkill
for this purpose, and an extra dependency).

I use subprocess regularly, but it doesn't work in this case because (a)
the point of using an interactive interpreter is so that I can interact
with the job *while it's running* and (b) I *still* wouldn't be able
exit the interactive shell cleanly (I'd have to look up the PID and kill
it via the shell -- very ugly and not portable).

-Matt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top