I have always been confused about Python's exception-handling model. I hope someone can clear up a few questions:
http://www.python.org/dev/doc/devel/ref/exceptions.html#l2h-225 says:
"When an exception is raised, an object (maybe None) is passed as the exception's value; this object does not affect the selection of an exception handler, but is passed to the selected exception handler as additional information. For class exceptions, this object must be an instance of the exception class being raised."
But unless I misunderstand the source, Luke, Python itself raises exceptions all over the place with PyErr_SetString(), which uses a class as the exception type and a string as the exception object. Other uses of PyErr_SetObject() that I've found /never/ seem to use an instance of the exception class as the exception object.
If I got that right, what's the meaning of the documentation I quoted? What rules must one actually follow when raising an exception?
This may be a case where reading the source is actually confusing. :-) When the exception type is a class and the exception value is not an instance of that class, eventually the class is instantiated with the value as argument (if the value is a tuple, it is used as an argument list). But there's an efficiency hack that tries to put off the class instantiation as long as possible. It is possible for C code to "catch" the exception and clear it without the instantiation happening, and then the instantiation costs are saved. Because C code rather frequently checks and clears exceptions, this can be a big win. Thus, in C, if you the exception value using PyErr_Fetch(), you may see a value that's not an instance of the class. But if you catch it in Python with an except clause, it will be instantiated before your except clause is entered. This is done by PyErr_NormalizeException(); its API docs provide a summary of what I just explained. --Guido van Rossum (home page: http://www.python.org/~guido/)