Exception as the primary error handling mechanism?

Chris Rebert clp2 at rebertia.com
Wed Jan 6 03:48:55 CET 2010


On Tue, Jan 5, 2010 at 5:45 PM, Phlip <phlip2005 at gmail.com> 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. (Yes yes I can
> write int_or_None(), etc...)

No, you can certainly decide yourself. You merely need be explicit
about it; you're leaving out the other tandem half of the couplet:
"*Unless* explicitly silenced." Throwing exceptions is only the
default because it tends to lead to more reliable code in that you're
forced to deal with the error condition by either catching an
exception or preventing one from being thrown (by, say, using a
different method in the API that just returns a default value
instead).

As an aside, I would guess the built-in types don't have default value
parameters for conversions partly because it'd be a bit less elegant
to implement; since None is a commonly used default value, they'd have
to use a different sentinel as said parameter's default value to
indicate that the caller wanted an exception raised, and having a
hierarchy of nil values in the core language detracts from the
language's elegance.

At any rate, if you like dict.get(), I don't see why, say,
my_int('nonnumeric', None) should be such a problem.

> 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 .

Exactly, that's explicitly silencing the error; no one ever said an
`except` clause was the only silencing mechanism. You're making your
intention clear by using .get() and passing in a desired default. I
agree this is a fine thing.

> Now the equivalent in a language that does not enjoy this false "Zen":
>
>  { 42: 'forty two' }[41]  # returns None
>  { 42: 'forty two' }.fetch(41, None)  # ibid
>  { 42: 'forty two' }.fetch(41)  # raises an exception
>
> The quicky validation is available if I _request_ it.

Seems like rather "fast-and-loose" programming if you don't care about
validation enough of the time to merit it being default. If your
programming is indeed so fast-and-loose, I refer you to the recent
comment about PHP (and other less "exception-happy" languages).

Anyway, I do totally agree that you should, if feasible, be provided
an easy way to designate a common error-handling strategy (for
example, in this case, by using a default value via .fetch()).

However, go too loose on error handling and exceptions and one ends up
with something like JavaScript with its infamous `undefined` value
which can make debugging a nightmare (whoever came up with the idea of
JS's `undefined` should be slapped upside the head).

Cheers,
Chris
--
http://blog.rebertia.com



More information about the Python-list mailing list