Catching Custom Python Exceptions

Python is often described as a language which doesn’t “surprise” people with strange edge cases.

Here’s one for you. Don’t peek at the answer, and try to predict the result.

>>> class NewException(Exception): pass
...
>>> try:
...    raise NewException, 'Error Message'
... except NewException, message:
...    pass
>>>   print message
???? you answer here
>>>   print message.__class__
???? you answer here

I always thought that the second argument in the except statement tallies with the second argument in the raise statement.

However this is actually wrong. The second argument is actually an instance of the Exception class which was thrown.

>>> class NewException(Exception): pass
...
>>> try:
...    raise NewException, 'Error Message'
... except NewException, message:
...    pass
>>>   print message
Error Message
>>>   print message.__class__
__main__.NewException
>>> # observe that message is not a string!
>>>  print message.args
('Error Message',)

Is there any reasons why it is done this way? A Python wart or because I should have read the manuals:

raise [expression ["," expression ["," expression]]]

  1. raise - re-raises the last expression that was active in the current scope
  2. raise MyException(”message”)
  3. raise MyException, “message” - “message” passed to constructor
  4. raise MyException, (”message”, “IO-882″) - (”message”, “IO-882″) passed to constructor
  5. raise MyException, None - constructor called without arguments
  6. raise …, …, traceback - reraises error transparently in an except clause

Python
Warts

4 Responses to “Catching Custom Python Exceptions”

  1. Simon writes:

    Well, the Python wart is that you can raise several ways, not that you receive an instance. It’s probably because in early Python you could only raise strings. With strings you’d need a way to pass additional information.

    If my reading of PEP 3109 is correct, the only way to raise exceptions with arguments in Python 3000 will be to create an exception instance with arguments passed as with any other object instantiation.

  2. Chui writes:

    The ‘wart’ in my mind is the mismatch between the “raise” signature and the “except” signature.

    i.e.
    raise Exception, “message”
    except Exception, <exception instance >

  3. Brian writes:

    But the raise Exception, “message” syntax is deprecated, only there for backward compatibility. With the raise Exception(”message”) syntax that should be used for all new code, theres no mismatch - you’re raising an exception instance, and that’s what you get in the except: block.

  4. Chui’s counterpoint » Blog Archive » More Warts in Python Exceptions writes:

    [...] I’ve previously blogged about a little Python wart in the way exceptions differ from the way it’s raised. [...]

Leave a Reply