[Python-Dev] Exception-handling model

Guido van Rossum guido@python.org
Fri, 09 Aug 2002 12:32:39 -0400

> 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

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/)