Re: [capi-sig] Exceptions with additional instance variables

On Mon, Dec 22, 2008 at 03:29, Guilherme Polo <ggpolo@gmail.com> wrote:
On Sun, Dec 21, 2008 at 11:02 PM, <chojrak11@gmail.com> wrote:
Hello,
I'm trying to implement custom exception that have to carry some useful info by means of instance members, to be used like:
try: // some code except MyException, data: // use data.errorcode, data.errorcategory, data.errorlevel, data.errormessage and some others
The question is - how to implement the instance variables with PyErr_NewException?
Using PyErr_NewException is fine. You must understand that an exception is a class, and thus PyErr_NewException creates one for you and returns it. Just like you would do with a class that has __dict__, set some attributes to what you want. That is, use PyObject_SetAttrString or something more appropriated for you.
Ok so I did the following. In init function (forget refcounting and error checking for a moment ;-)
PyObject *dict = PyDict_New(); PyDict_SetItemString(dict, "errorcode", PyInt_FromLong(0)); static PyObject *myexception = PyErr_NewException("module.MyException", NULL, dict); PyModule_AddObject(module, "MyException", myexception);
It worked more or less as expected, the help shown:
| ---------------------------------------------------------------------- | Data and other attributes defined here: | | errorcode = 0 | | ----------------------------------------------------------------------
Then I did the following when raising the exception:
PyObject_SetAttrString(myexception, "errorcode", PyInt_FromLong(111)); PyErr_SetString(myexception, "Bad thing happened"); return NULL;
and the test code was: try: do_bad_thing(); except MyException, data:
and you surely already guessed it -- data.errorcode was 0.... Not only that, module.MyException.errorcode was also 0...
What I'm doing wrong? I certainly don't get the idea of exceptions in Python, especially what is being raised - a class or an instance? If the latter - how's the class instantiated? If not - what about values in different threads? The docs are so vague about that...
Thanks again in advance, Chojrak

chojrak11@gmail.com wrote:
Ok so I did the following. In init function (forget refcounting and error checking for a moment ;-)
PyObject *dict = PyDict_New(); PyDict_SetItemString(dict, "errorcode", PyInt_FromLong(0)); static PyObject *myexception = PyErr_NewException("module.MyException", NULL, dict); PyModule_AddObject(module, "MyException", myexception);
It worked more or less as expected, the help shown:
| ---------------------------------------------------------------------- | Data and other attributes defined here: | | errorcode = 0 | | ----------------------------------------------------------------------
Then I did the following when raising the exception:
PyObject_SetAttrString(myexception, "errorcode", PyInt_FromLong(111)); PyErr_SetString(myexception, "Bad thing happened"); return NULL;
and the test code was: try: do_bad_thing(); except MyException, data:
and you surely already guessed it -- data.errorcode was 0.... Not only that, module.MyException.errorcode was also 0...
What I'm doing wrong? I certainly don't get the idea of exceptions in Python, especially what is being raised - a class or an instance? If the latter - how's the class instantiated? If not - what about values in different threads? The docs are so vague about that...
The quick way to fix your problem might be to write the exception code in Cython like thís:
class MyException(Exception):
def __init__(self, errorcode, message):
super(MyException, self).__init__(self, message)
self.errorcode = errorcode
and use that instead. You can also make it an exception class if you like, by declaring the Exception class as an external type (requires Py2.5+). In this case, Cython can generate a header file for you that declares your new extension type.
Stefan
participants (2)
-
chojrak11@gmail.com
-
Stefan Behnel