2024-08-26
What's going on with 'quit' in an interactive CPython session (as of 3.12)
We're probably all been there at some time or the other:
$ python [...] >>> quit Use quit() or Ctrl-D (i.e. EOF) to exit
It's an infamous and frustrating 'error' message and we've probably
all seen it (there's a similar one for 'exit
'). Today I was
reminded of this CPython behavior by a Fediverse conversation and as I was
thinking about it, the penny belatedly dropped on what is going
on here in CPython.
Let's start with this:
>>> type(quit) <class '_sitebuiltins.Quitter'>
In CPython 3.12 and earlier, the CPython interactive interpreter evaulates Python statements; as far as I know, it has little to no special handling of what you type to it, it just evaluates things and then prints the result under appropriate circumstances. So 'quit' is not special syntax recognized by the interpreter, but instead a Python object. The message being printed is not special handling but instead a standard CPython interpreter feature to helpfully print the representation of objects, which the _sitebuiltins.Quitter class has customized to print this message. You can see all of this in Lib/_sitebuiltins.py, along with classes used for some other, related things.
(Then the 'quit' and 'exit' instances are created and wired up in Lib/site.py, along with a number of other things.)
This is changing in Python 3.13 (via), which defaults to using a new interactive shell, which I believe is called 'pyrepl' (see Libs/_pyrepl). Pyrepl has specific support for commands like 'quit', although this support actually reuses the _sitebuiltins code (see REPL_COMMANDS in Lib/_pyrepl/simple_interact.py). Basically, pyrepl knows to call some objects instead of printing their repr() if they're entered alone on a line, so you enter 'quit' and it winds up being the same as if you'd said 'quit()'.