[capi-sig] Exceptions with additional instance variables

Stefan Behnel stefan_ml at behnel.de
Mon Dec 22 13:35:27 CET 2008

chojrak11 at 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.



More information about the capi-sig mailing list