The rap against "while True:" loops

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Oct 18 13:28:09 CEST 2009


On Sat, 17 Oct 2009 13:12:52 +0100, Tim Rowe wrote:

> 2009/10/17 Steven D'Aprano <steve at remove-this-cybersource.com.au>:
> 
>> No, you have a fundamental misunderstanding. They're called exceptions,
>> not errors, because they represent exceptional cases. Often errors are
>> exceptional cases, but they're not the only sort of exceptional case.
> 
> The whole reason for the mechanism, across all languages that have it,
> is to deal with situations that you don't know how to deal with locally.

That confuses me. If I call:

y = mydict[x]

how does my knowledge of what to do if x is not a key relate to whether 
the language raises an exception, returns an error code, dumps core, or 
prints "He's not the Messiah, he's a very naughty boy" to stderr?

You seem to be making a distinction of *intent* which, as far as I can 
tell, doesn't actually exist. What's the difference in intent between 
these?

y = mydict[x]
if y == KeyErrorCode:
    handle_error_condition()
process(y)


and this?

try:
    y = mydict[x]
except KeyError:
    handle_error_condition()
process(y)


Neither assumes more or less knowledge of what to do in 
handle_error_condition(). Neither case assumes that the failure of x to 
be a key is an error:

try:
    y = mydict[x]
except KeyError:
    process()  # working as expected
else:
    print 'found x in dict, it shouldn't be there'
    sys.exit()

Either way, whether the language uses error codes or exceptions, the 
decision of what to do in an exceptional situation is left to the user.

If you'll excuse me pointing out the bleedin' obvious, there are 
differences between error codes and exceptions, but they aren't one of 
intention. Error codes put the onus on the caller to check the code after 
every single call which might fail (or have a buggy program), while 
exceptions use a framework that do most of the heavy lifting.


> That's why they have the overhead that they do.

Exceptions don't have one common overhead across all languages that use 
them. They have different overhead in different languages -- they're very 
heavyweight in C++ and Java, but lightweight in Python. The Perl 
Exception::Base module claims to be lightweight. The overhead of 
exceptions is related to the implementation of the language.


>> Python uses exceptions for flow control:
> 
> Yes, and in some cases I think that's a serious language wart. Not
> enough to put me off the language, but a serious wart nevertheless.

I disagree with that. I think exceptions are a beautiful and powerful way 
of dealing with flow control, much better than returning a special code, 
and much better than having to check some status function or global 
variable, as so often happens in C. They're more restricted, and 
therefore safer, than goto. They're not a panacea but they're very useful.


>> Similarly, it's hardly an *error* for [1, 2, 3].index(5) to fail -- who
>> is to say that the list is supposed to have 5 in it? ValueError (a
>> slightly misleading name in this situation) is used to indicate an
>> exceptional, but not unexpected, occurrence.
> 
> That one is, I think, a legitimate use of an exception. The result
> returned by index is defined if the index is in bounds. If not, index
> doesn't know whether it was supposed to be in bounds or not, and so
> can't handle the case locally. It could suggest an error or merely
> (IMHO) poor programming. Because index cannot know what the proper
> action is, an exception is the appropriate response.

I think you're confused about what list.index(obj) does. You seem to me 
to be assuming that [1,2,3].index(5) should return the item in position 5 
of the list, and since there isn't one (5 is out of bounds), raise an 
exception. But that's not what it does. It searches the list and returns 
the position at which 5 is found.

Of course list.index() could have returned an error code instead, like 
str.find() does. But str also has an index() method, which raises an 
exception -- when handling strings, you can Look Before You Leap or Ask 
For Forgiveness Instead Of Permission, whichever you prefer.


>> Likewise, KeyboardInterrupt is used to allow the user to halt
>> processing; SystemExit is used to shut down the Python virtual machine;
>> and warnings are implemented using exceptions.
> 
> Again, I think it's fair to treat a program being killed from outside as
> an exception as far as the program is concerned. 

No, it's not being killed from outside the program -- it's being 
*interrupted* from *inside* the program by the user. What you do in 
response to that interrupt is up to you -- it doesn't necessarily mean 
"kill the program".

If you kill the program from outside, using (say) kill or the TaskManager 
or something, you don't necessarily get an exception. With kill -9 on 
POSIX systems you won't get anything, because the OS will just yank the 
carpet out from under your program's feet and then drop a safe on it to 
be sure.



-- 
Steven



More information about the Python-list mailing list