[Python-Dev] a quit that actually quits

Fernando Perez fperez.net at gmail.com
Wed Dec 28 19:36:35 CET 2005


Alex Martelli wrote:

> 
> On Dec 28, 2005, at 3:24 AM, Michael Hudson wrote:

>> The thing that bothers me about it is that the standard way you tell
>> python to do something is "call a function" -- to me, a special case
>> for exiting the interpreter seems out of proportion.
> 
> Just brainstorming, but -- maybe this means we should generalize the
> idea?  I.e., allow other cases in which "just mentioning X" means
> "call function Y [with the following arguments]", at least at the
> interactive prompt if not more generally.  If /F's idea gets
> implemented by binding to names 'exit' and 'quit' the result of some
> factory-call with "function to be called" set to sys.exit and
> "arguments for it" set to () [[as opposed to specialcasing checks of
> last commandline for equality to 'exit' &c]] then the implementation
> of the generalization would be no harder.  I do find myself in
> sessions in which I want to perform some action repeatedly, and
> currently the least typing is 4 characters (x()<enter>) while this
> would reduce it to two (iPython does allow such handy shortcuts, but
> I'm often using plain interactive interpreters).
> 
> If this generalization means a complicated implementation, by all
> means let's scrap it, but if implementation is roughly as easy, it
> may be worth considering to avoid making a too-special "special
> case" (or maybe not, but brainstorming means never having to say
> you're sorry;-).

Allow me to add a few comments, here: as the ipython author, I happen to have
thought an awful lot about all these issues.  

First, your suggestion of incorporating 'autocalling' ( the automatic 'foo a' ->
'foo(a)' transformation) into the core python interpreter may not be a very
good idea.  The code that does this is precisely the most brittle, delicate
part of ipython, a little regexp/eval/introspection dance that tries really,
really hard to understand whether 'foo' is a string that will point to a
callable once evaluated, but without eating generators, causing side effects,
or anything else.  I know it sounds silly, and perhaps it's just my
limitations, but it has taken several years to flesh out all the corner cases
where this code could fail (and in the past, a few really surprising failure
cases have been found).

In ipython, this functionality can still be turned off (via %autocall) at any
time, in case it is not working correctly.  You are welcome to look at the
code, it's the _prefilter method here:

http://projects.scipy.org/ipython/ipython/file/ipython/trunk/IPython/iplib.py

So while I think that this is extremely useful in a third-party library like
ipython, it's probably a little too delicate for the core, official interpreter
where reliability is so absolutely critical.  In fact, my own standard is that
I trust the CPython prompt as a test of 'doing the right thing', so I like that
it remains simple and solid.

Now, on to the wider discussion started by the quit/exit debate: the problem is
that we are here trying to make some particular words 'interactive commands' in
a language that doesn't have such a notion to begin with.  The tension of how
best to implement it, the various low-level tricks proposed, etc, stems (I
think) from this underlying fact.  

In IPyhton, I've convinced myself that this is a problem whose proper solution
requires an orthogonal command subsystem, the 'magics' (credit where credit is
due: the magic system was already in IPP, Janko Hauser's library which was one
of ipython's three original components; Janko understood the issue early on and
got it right).  This creates a separate namespace, controlled by a
disambiguation character (the % prefix in ipython), and therefore allows you to
cleanly offer the kind of behavior and semantics which are more convenient for
command-line use (whitespace argument separation, --dashed-options) without
colliding with the underlying language.  

By having the 'magic' command system be separate, it is also trivially
extensible by the users (see
http://ipython.scipy.org/doc/manual/node6.html#SECTION00062000000000000000 for
details).  This means that instead of going into a never-ending rabbit-chase of
special cases, you now have a well-defined API (IPython's is primitive but it
works, and we're cleaning it up as part of a major rework) where users can add
arbitrary command functionality which remains separate from the language
itself.

The main point here is, I think, that any good interactive environment for a
programming language requires at least TWO separate kinds of syntax:

1. the language itself, perhaps with aids to economize typing at the command
line (ipython offers many: auto-calling, auto-quoting, readline tricks, input
history as a Python list, output caching, macros, and more).

2. a set of control commands, meant to manipulate the environment itself.  These
can obviously be implemented in the underlying language, but there should be a
way to keep them in a separate namespace (so they don't collide with user
variables and can be always called).


I'll be glad to discuss this further, either here or on the ipython lists where
this is probably more appropriate.  But I wanted to give the python-devs some
perspective on this, from having spent a lot of time dealing directly with the
isues.  

Finally, I'd like to provide a bit of a plea: I hope that python itself doesn't
end up polluting the core sys namespace with too many special things for
interactive use.  I think that a proper interactive console is best implemented
as a separate extension (ipython, pycrust, idle, etc).  Putting all these
special-case things into sys ends up propagating everywhere, and potentially
colliding with such systems (ipython has its own sys.excepthook, for example). 
Please keep the core (sys is very much part of the core) as clean as possible,
and let the interactive shell writers add the functionality outside.

Best,

f

ps - thanks to this thread, I've changed ipython from having the old-style
quit/exit strings with the message, to being magics which exit.  It had always
had %Quit/%Exit for unconditional exit, but now (SVN) it also has %quit/%exit
which honor the confirm_exit rc setting.



More information about the Python-Dev mailing list