Python Mystery Theatre -- Episode 1: Exceptions
Michael Chermside
mcherm at mcherm.com
Tue Jul 15 08:02:43 EDT 2003
First of all, Raymond THANK YOU. This is lots of fun, and educational too.
In fact, I'm nominating it for my favorite c.l.py posting so far this
year!
So... here's how I did. [** SPOILERS BELOW **]
ACT I:
This one stumped me the longest... I stared and stared and just
couldn't figure it out. But when I came back the next morning
it was obvious.
"except foo, bar" catches things of type foo, and binds bar
to the object caught. To catch multiple types you stick them
in a tuple. (This beats out Java where there's no way I know
of to catch multiple types.) Design wise, I think the syntax
is a little odd, but not worth changing.
ACT II:
Easy... when you write "raise foo, bar" Python executes foo(bar)
and then raises that object. So of course the object, when you
catch it, is an instance.
ACT III:
It took me a while to figure out what you were EXPECTING here,
I guess a more complete sumary would be that "raise foo, bar"
raises the object "foo(bar)", while "raise foo" either raises
the object "foo" or the object "foo()". The rules for which to
do are simply that if foo is of type "type" (ie, it's an old-style
class) then it raises "foo()", otherwise "foo". In my opinion,
this is an unnecessary bit of DWIM (DoWhatIMean), and things
would be much cleaner if you just always said "raise foo" and
it raised the object "foo" -- at worst you'd need an extra set
of parenthesees -- but we recently discussed this in PEP-317 and
in the end, Guido (and others) succeeded in convincing me (and
others) that it's not worth changing, and he mapped out a plan
for how to make the DWIM decision (to raise "foo" or "foo()")
after the change to new-style classes. I do, however, consider
if a minor wart.
Anyhow, it's thanks to the PEP-317 discussions that I understood
this one.
http://mail.python.org/pipermail/python-dev/2003-June/036162.html
ACT IV:
I was EXPECTING this one, since it's an exceptions "gotcha" that
I already know about. Exception catching is done by object identity,
not equality. Normally, you catch with the CLASS of the instance
that got raised, so that's OK, but if you raise string exceptions
then it's got to be the same object, not just an equivalent
string.
Solution? Don't raise strings.
ACT V:
Puzzled me for a couple of minutes, but then I realized that
LookupError is an ancestor class of KeyError. That design is
a GOOD thing... if your exceptions are in a meaningful hierarchy
then you can catch whole sections of the hierarchy without having
to name each and every exception individually.
So there we have it... it took me one overnight of cogitation, but
I got them all without even cracking a reference book (although I
admit I had to fire up the interpreter to double-check how to catch
multiple exception types together).
For those who are just hungering for more, here's another (not quite
so good as Raymond's, but might confuse someone):
>>> try:
... raise IndexError
... except IndexError, errObject:
... print errObject
...
>>>
-- Michael Chermside
More information about the Python-list
mailing list