Exception-handling model
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? TIA, Dave ----------------------------------------------------------- David Abrahams * Boost Consulting dave@boost-consulting.com * http://www.boost-consulting.com
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/)
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
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
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> the 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/)
participants (2)
-
David Abrahams
-
Guido van Rossum