4

The built-in function quit() behaves differently in Python-3.x and IPython 3. The following code prints Hello if executed in IPython, but does not print anything in Python:

quit()
print("Hello")

What is the purpose of quit() in IPython? What was the reason for changing its behavior?

DYZ
  • 55,249
  • 10
  • 64
  • 93
  • 1
    It's for quitting out of the interpreter session...? That works for me. Anyway, it is perhaps more precise to say what is the difference between the normal interactive Python interpreter REPL and IPython. IPython isn't distinct from Python 3.x... Anyway, are you actually running scripts with `ipython`? The `quit` function is just there for exiting from a python shell session, and shouldn't be used in scripts anyway. – juanpa.arrivillaga Dec 07 '16 at 01:11
  • @juanpa.arrivillaga Since "Hello" is printed, apparenlty quit() in IPython does not really quit the interpreter - at least not immediately. – DYZ Dec 07 '16 at 01:14
  • 1
    it does if you are in an interpreter *shell session*, which is what it is meant to do. This is likely some loose end because no one thought you'd use `quit` outside of the interactive prompt. – juanpa.arrivillaga Dec 07 '16 at 01:16
  • If I type `quit();print(10)` in the shell, it still prints 10 before it quits. – DYZ Dec 07 '16 at 01:17
  • Well, ShadowRanger looked into it and has posted an answer that looks to be complete. Anyway, `quit` is not a built-in function. – juanpa.arrivillaga Dec 07 '16 at 01:22
  • Actually, it is: https://docs.python.org/3/library/constants.html – DYZ Dec 07 '16 at 01:23

1 Answers1

6

It looks like IPython's quit/exit "function" simplifies to just setting a flag to say "you should exit when this is next checked". It doesn't raise SystemExit itself, so it's presumably dependent on an intermittent check that, if you queue both commands at once, isn't performed until the second command finishes.

You can check it yourself at the IPython prompt, first run quit?? to see that it's a callable class whose __call__ delegates to self._ip.ask_exit(). Next, run quit._ip.ask_exit?? and you'll see that ask_exit just sets a flag, self.exit_now = True (and it's a plain attribute if you check it, not a property with hidden code execution).

You're welcome to track down where IPython is checking that; I'm guessing it's done after any given line or cell of IPython completes.

Fundamentally, the difference is that quit in IPython has never been the same as quit in regular Python's interactive interpeter; quit/exit as a built-in is intended to be replaced for alternate interactive interpreters, and needn't behave exactly the same. If you want a consistent exit behavior, import sys and run sys.exit(), which is also the correct way to exit early inside a script, and is not intended as a hook for the interactive prompt.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • `quit` isn't even really a built-in. – juanpa.arrivillaga Dec 07 '16 at 01:20
  • As I said above, it is: https://docs.python.org/3/library/constants.html – DYZ Dec 07 '16 at 01:23
  • 1
    @juanpa.arrivillaga: Sort of. It's an instance of a special `Quitter` class, that looks to be implemented in Python (it has helpful extras like a `repr` that reminds you you need to add parentheses if you type `quit` and forget to call it). It's a built-in only in the sense that it ships with core Python, not an actual part of the CPython interpreter core or the C level implementation of `__builtins__` or anything, it just gets shoved into `__builtins__` by the `site` package on startup (and technically, the `site` auto-import can be disabled, though that's rarely done). – ShadowRanger Dec 07 '16 at 01:29