foxfirefey: Smiley faces are born through factorized mechanical torture. (grimace)
[personal profile] foxfirefey posting in [community profile] python
Most of the time when I want to quit using you, I do something like this:

>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit

I am not sure why, if you know enough about what I want to give me a warning message about what I should Properly Do, you couldn't just exit and save me the headdesking trouble!

Other than that, I love you, so I am hoping you have a Really Good reason for this that I just don't know about.

(no subject)

Date: 2010-04-24 05:55 am (UTC)
aquaeri: My nose is being washed by my cat (Default)
From: [personal profile] aquaeri
I always wondered about that, myself.

(no subject)

Date: 2010-04-24 06:43 am (UTC)
yvi: Kaylee half-smiling, looking very pretty (Default)
From: [personal profile] yvi
And that's why you kill it with fire Ctrl-D :)

(no subject)

Date: 2010-04-24 08:39 am (UTC)
dimitar: Hiking in the Alps (Default)
From: [personal profile] dimitar
Guessing user intentions in situations like this could lead to even more serious trouble. It's good when software has clearly defined rules and sticks to them, in my opinion.

(no subject)

Date: 2010-05-01 01:14 pm (UTC)
perquisitor_omnia: Green Triskele with Glowing Background (Default)
From: [personal profile] perquisitor_omnia
Technical Explanation: It is because all commands to the python interpreter are either keywords or built-in functions of Python. exit() would be how one would exit a python script as well.

Easy Explanation: It is because most programmers are pathological sticklers for exactness.

(no subject)

Date: 2010-05-01 10:53 pm (UTC)
perquisitor_omnia: Green Triskele with Glowing Background (Default)
From: [personal profile] perquisitor_omnia
Probably because they thought that the error message as it stands was more informative? And as I said they are pedants. And I must say that the python interactive interpreter is much more picky than PERL's "if it looks like it might be program code it probably is" mentality.

(no subject)

Date: 2011-03-01 09:43 am (UTC)
bookofjude: (Default)
From: [personal profile] bookofjude
This is actually really confusing and it annoyed me once so I looked into it!

Basically, Python has a module called which provides a lot of Cool Stuff. One of the things it does is scan the standard prefixes for .pth files, which are then appended to PYTHONPATH — so include a .pth file with relative paths in your distutils scripts via data_files = [("lib/site-packages", "your_data_file.pth")] if you want to install to a sub-folder of lib/site-packages, which wouldn't automatically be checked (this bit me with the Windows-compiled binary for the python-rsvg module — it installs to lib/site-packages/gtk-2.0/rsvg.pyd, and that's never put into PYTHONPATH, so Python never knows that you have python-rsvg installed so trying to import it always fails.) — but it also provides exit and quit.

These are neither statements (like print, which, confusingly enough, has ceased to be a statement in Python 3.0 and is now a function — and it can be treated like a function from Python 2.7 onwards) nor functions (though they're callable).

They're actually instances of site.Quitter — which isn't available as a class via site.Quitter; this further confuses matters — which you can find out with:

>>> type(exit)
<class 'site.Quitter'>
>>> type(quit)
<class 'site.Quitter'>

(Interestingly enough:

>>> exit == quit
>>> type(exit) is type(quit)

They're both instances of site.Quitter, but not the same instance.)

So, as they're instances rather than statements, one cannot just execute exit or quit as you might expect (another digression: someone filed a bug regarding the site-provided exit and quit methods polluting the builtin namespace, but it was not acted upon because some people have grown to rely on exit and quit being available outside of the interpreter — so it seems the original intent was that these were only to be available via the interpreter!). Instead, you have to call them as functions, just like all other built-in functions (dir, sorted, and, related but explained later, help).

To get around the fact that most people expect exit and quit to be statements, it was decided (at some point in time, by person or persons unknown) to give them a little dash of "magic". To side-step the issue and come at it from another angle, when one types the name of a variable (almost everything in Python is a variable), it prints an internal representation of that variable.

For other built-ins, such as dir, calling repr(dir) returns '<builtin function dir>', for example. Thus:

>>> dir
<built-in function dir>

This is because functions (and, built-in functions, which derive from the main function type), by default, provide a __repr__ method; this magic method is called whenever repr is called — either repr looks for this method, or this method is called instead of repr, or this method calls repr: I can never remember the exact order of things!

Thus, any class which defines a __repr__ method, when an instance of that class is created, and its variable name is typed into the interpreter, will have that method called, and the value it returns will be printed. Therefore, we can do the following:

>>> class ReprTester (object):
... def __repr__ (self):
... return "Executing me as an instance calls repr(me) and displays the result!"
>>> test = ReprTester()
>>> test
Executing me as an instance calls repr(me) and displays the result!

So, when one performs the following in the interpreter:

>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit

You're actually indirectly calling print(repr(exit)), and that's the "magic" I mentioned earlier. So now, whenever someone calls exit (or quit), they get a pretty little reminder telling them to call exit() (or quit()) instead.

Fun side-point: because the code directly calls __repr__ of the exit object, we can actually create a new class that actually does exit whenever it's called as though it were a statement — though this has the side effect of whenever you call repr(exit) your interpreter exits:

>>> class FancyQuitter (object):
... def __repr__ (self):
... __builtins__.exit()
>>> exit = FancyQuitter()
>>> exit

So, if you really, really couldn't stand it, there's probably a way to use this object to consistently replace the built-in exit and quit objects whenever you start the interpreter. However, I just prefer to use Ctrl-D!

(And one final side-note: I think the messages are different across platforms, but Ctrl-D doesn't work on Windows. Instead, you have to use Ctrl-Z. For someone who switches consistently between platforms, I've developed the following technique: Ctrl-C Ctrl-D Ctrl-Z Ctrl-C Ctrl-Z Ctrl-D.

Doing this in quick succession usually results in the thing finally oh finally quitting. Alternately, hitting the Window manager's close button or (though not on Windows — this not working is very annoying to me) Alt-F4 is a sure-fire way to end that pesky, annoying, infuriating interpreter!)

(Oh, a final final side-note: while I exclaim that it's __repr__ that does all of the 'good' work above, there's every chance that __repr__ is actually just calling str(exit) and it's the __str__ function that prints the pretty statement. So, where or when necessary, replace all references to __repr__ with __str__!)

(Okay, now a final note, because I mentioned it earlier: help is exactly the same thing, except it does documentation rather than quitting the program, and is an instance of site._Helper — another "invisible" class.)
Edited Date: 2011-03-01 09:58 am (UTC)

February 2017

2627 28    

Style Credit

Expand Cut Tags

No cut tags