FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Graceful forced exit? · Issue #9944 · ipython/ipython · GitHub

Repository navigation

Graceful forced exit? #9944

Open
Open

Description

Is there a way for an application to signal to ipython that it should exit gracefully? My use case is installing a signal handler to force IPython to exit.

I would like something like this to work:

In [1]: import sys, signal

In [2]: def exit_now(*args): sys.exit()

In [3]: signal.signal(signal.SIGALRM, exit_now)
Out[3]: 0

In [4]: signal.alarm(2)
Out[4]: 0

In [5]:

It used to be that forcing an EOF on stdin would work, but prompt_toolkit does not handle that correctly anymore. See also prompt-toolkit/python-prompt-toolkit#392

Activity

  1. takluyver commented on Sep 13, 2016

    Member

    get_ipython().ask_exit() is the official way, I think.

    We've always caught SystemExit, and I presume that's because people sometimes %run code which uses sys.exit() to finish, while the user doesn't want to be booted out of the interactive prompt.

  2. minrk commented on Sep 13, 2016

    Member

    Shouldn't we be doing a graceful exit on SIGTERM? I know we aren't, but it seems like we should.

  3. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    Shouldn't we be doing a graceful exit on SIGTERM?

    That is what I am trying to do in https://github.com/sagemath/cysignals. However, the trick which used to work with IPython 4 no longer works now.

  4. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    We've always caught SystemExit, and I presume that's because people sometimes %run code which uses sys.exit() to finish, while the user doesn't want to be booted out of the interactive prompt.

    I understand that and I am not asking that to change.

  5. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    get_ipython().ask_exit() is the official way, I think.

    That works on the IPython part, but not on the prompt_toolkit part. Executing ask_exit() while prompt_toolkit is waiting for a prompt will not cause IPython to exit. So this looks more like a prompt_toolkit problem and not an IPython problem.

  6. takluyver commented on Sep 13, 2016

    Member

    That's expected, I think - ask_exit sets a flag which we only check in our interaction loop, not while PT is running the event loop for the prompt. However, I'm a bit confused about why you want to exit programmatically while there's a prompt displayed.

    Maybe we should just be installing a signal handler for SIGTERM. How would that interact with what you're trying to do?

  7. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    Maybe we should just be installing a signal handler for SIGTERM

    The whole point of this issue and prompt-toolkit/python-prompt-toolkit#392 is that it's not so simple to "just" do that.

    How would that interact with what you're trying to do?

    It is essentially exactly what I'm trying to do, except that I also care about plain Python (not IPython) prompts. And I want this both for SIGHUP and SIGTERM.

  8. takluyver commented on Sep 13, 2016

    Member

    Does this work:

    ip = get_ipython()
    ip.ask_exit()
    ip.pt_cli.exit()
    
  9. takluyver commented on Sep 13, 2016

    Member

    Looking at the code, I suspect that will give you the 'are you sure' prompt. If so, try changing the last line to:

    ip.pt_cli.set_return_value(None)
  10. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    Neither of those works. Both of them do not react immediately, but only after pressing some key. This is logical, because none of the lines of code that you write would cause the input prompt to be aborted.

    With ip.pt_cli.set_return_value(None), you even get an exception:

    Traceback (most recent call last):
      File "/usr/local/src/sage-config/local/bin/ipython", line 5, in <module>
        start_ipython()
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/__init__.py", line 119, in start_ipython
        return launch_new_instance(argv=argv, **kwargs)
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/traitlets/config/application.py", line 596, in launch_instance
        app.start()
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/ipapp.py", line 348, in start
        self.shell.mainloop()
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.py", line 402, in mainloop
        self.interact()
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.py", line 385, in interact
        code = self.prompt_for_code()
      File "/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.py", line 322, in prompt_for_code
        return document.text
    AttributeError: 'NoneType' object has no attribute 'text'
    
  11. takluyver commented on Sep 13, 2016

    Member

    In that case I think it's up to the implementation of the PT event loop.

    I remain puzzled as to how you're arriving at this scenario, though. AIUI, signals are handled in the main thread, but if that's running the IPython interface, where's your code running? Or are you running IPython in a background thread for some reason?

  12. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    I don't understand your question:

    I remain puzzled as to how you're arriving at this scenario, though.

    Which "scenario"?

    where's your code running?

    Which "code"?

  13. takluyver commented on Sep 13, 2016

    Member

    Which "scenario"?

    The scenario where an IPython prompt is displayed and some other code wants to exit it programmatically.

    Which "code"?

    The code that receives the signal and wishes to quit the prompt.

    Maybe it's coming from another event loop using the inputhook integration?

  14. jdemeyer commented on Sep 13, 2016

    ContributorAuthor

    The scenario is really exactly what you described. I want to exit IPython gracefully when receiving a SIGTERM signal.

    I wasn't even aware of multiple threads. Anyway, my code is running in whatever thread is handling the signal.

  15. takluyver commented on Sep 13, 2016

    Member

    Right, signal handlers preempt regular execution. Don't mind me...

  16. added this to the 5.2 milestone on Sep 13, 2016
  17. added a commit that references this issue on Jan 19, 2017
    49c20c5
  18. takluyver commented on Jan 19, 2017

    Member

    #10185 is my attempt to deal with this.

  19. modified the milestones: 5.3, 5.2 on Jan 28, 2017
  20. modified the milestones: 5.3, 5.4 on Feb 23, 2017
  21. ivanov commented on May 17, 2017

    Member

    @jdemeyer I just want to mention that if you would like the old (IPython <= 4.x) readline interface, it is now available separately as rlipython.

    pip install rlipython
    python -c "import rlipython as r; r.install()"
    

    Right now, it only works in IPython 6.0 (Python 3), but it will also work in Python 2 with the next IPython 5 release (5.4).

  22. modified the milestones: wishlist, 5.4 on May 29, 2017
  23. techtonik commented on Jul 6, 2018

    Contributor

    From prompt-toolkit/python-prompt-toolkit#392 (comment) prompt toolkit allows this:

    from prompt_toolkit.application.current import get_app
    
    get_app().exit(exception=EOFError)
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL