Programmatically exit the REPL

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matthew Fitzgibbons

    Programmatically exit the REPL

    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.Threa d(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_progr am()
    called end_the_program ()
    # but we did exit here
    Desktop$


    -Matt
  • Alexander Schmolck

    #2
    Re: Programmaticall y exit the REPL

    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 <elessar@nienna .orgwrites:
    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.Threa d(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_prog ram()
    called end_the_program ()
    # but we did exit here
    Desktop$
    >
    >
    -Matt
    --

    Comment

    • Matthew Fitzgibbons

      #3
      Re: Programmaticall y exit the REPL

      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

      Comment

      • Matthew Fitzgibbons

        #4
        Re: Programmaticall y exit the REPL

        Almar Klein wrote:
        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 <elessar@nienna .org
        <mailto:elessar @nienna.org>>
        >
        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

        Comment

        Working...