Exception as the primary error handling mechanism?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Jan 6 00:10:28 EST 2010


On Tue, 05 Jan 2010 17:45:58 -0800, Phlip wrote:

> On Jan 5, 5:01 pm, Chris Rebert <c... at rebertia.com> wrote:
> 
>> > Why can't int('nonnumeric') return None?
>>
>> Errors should never pass silently.
> 
> You are saying I, as the programmer, cannot decide what is an error and
> what is a pass-thru. The decision is made for me.

Every function decides for you what is an error and what isn't. 

>>> max()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: max expected 1 arguments, got 0


But I wanted it to return (sys.maxint - 7). How DARE the creator of the 
language decide that it should be an error instead of returning the 
arbitrary result I choose!

Not.



> (Yes yes I can write int_or_None(), etc...)

That's right. As a programmer, your job is to program. If a language 
doesn't provide a function you want, write your own using the primitives 
available to you.



> Here's a super easy example:
> 
>   { 42: 'forty two' }.get(41, None)
> 
> Because I can supply a default, I can decide what is an error and what
> is .


You can ALWAYS decide what is an error.


d = {42: 'forty two'}
try:
    d[41]
except KeyError:
    print "All is good, no problems, dict does not contain 41"
except:
    print "WARNING WARNING WARNING!!!"
    print "FATAL ERROR: dict contains 41!!!"
    sys.exit()


You do so by programming. As a programmer, that's your job.


> Now the equivalent in a language that does not enjoy this false "Zen":
> 
>   { 42: 'forty two' }[41]  # returns None

Suppose you have a dict d supplied from somewhere else. You don't know 
what's in it. You do this:

d[41]

and you get a result None. Does this mean that the dict looks like this?

    d = {}

or like this?

    d = {41: None}




> { 42: 'forty two' }.fetch(41, None)  # ibid 

In Python, "fetch" is spelled "get".

> { 42: 'forty two' }.fetch(41)  # raises an exception

In Python, that would be spelled {42: 'forty two'}[41]


> The quicky validation is available if I _request_ it.

When you write d[41] you are requesting it. If you don't want it, use get 
instead.



>> Quibbling over a mere one more line of code (or writing one short
>> function) seems a bit petty.
> 
> Because that "Zen of Python" is an empty sophistry that forces me to add
> a "mere one more line of code" over and over again...

If you're writing that one line of code over and over again, that's a 
good sign that you're doing it wrong and should rethink your strategy.




>> > (A related question - why can't I just go 'if record = method():  use
>> > (record)'. Why extra lines just to trap and assign the variable
>> > before using it?)
>>
>> I believe that's disallowed so as to prevent the subtle bugs seen in C
>> code which result from when someone makes a typo and omits the second
>> "=" in their `if foo == bar():` test.
> 
> Don't prevent me from using a technique just because others had trouble
> with it.


Any language allows and prevents certain techniques, simply by the very 
nature of the language. Every language has it's own syntax: you can't 
write weakly-typed stack-based concatenative code (like Forth) in Java, 
or strongly-typed dynamic object-oriented Python code in Pascal. Every 
language forces the programmer to use some features and avoid others.


> And if bar() == foo is the superior technique anyway, because the ==
> happens in chronological and lexical order after the bar() call.

That makes no sense.



-- 
Steven



More information about the Python-list mailing list