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