[Python-Dev] Exception-handling model

David Abrahams dave@boost-consulting.com
Fri, 9 Aug 2002 12:57:12 -0400

Thanks, Guido and Jeremy! I thought something like that might be the case,
but then couldn't find the code which did the work... I never expected the
instantiation to be deferred in that way so I never looked further than the
code which actually does the raising.

It would probably be useful to put pointers to the PyErr_NormailzeException
behavior right at the top of the API docs for exception-handling, since
making sense out of basic facilities like PyErr_SetString() depends on it.

           David Abrahams * Boost Consulting
dave@boost-consulting.com * http://www.boost-consulting.com

From: "Guido van Rossum" <guido@python.org>
> > I have always been confused about Python's exception-handling model. I
> > 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
> > 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
> > 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/)