[C++-sig] export custom C++ exception to Python so it can be raisedby python

Martin Hellmich mhellmic at cern.ch
Tue Nov 6 15:35:10 CET 2012


Hi Giuseppe,

On 11/06/2012 10:08 AM, Giuseppe Corbelli wrote:
> On 05/11/2012 18:51, Martin Hellmich wrote:
>> Hi,
>>
>> I have a custom exception in C++ that I would like to use in Python.
>>
>> Let's call it MyException with custom constructor and members (an
>> implementation is below).
>> I would like to expose it to python so that I can raise it:
>>
>>  > raise MyException(-1, 'tragic error')
>>
>> The perfect way that I can imagine is to tell boost::python to base
>> the class
>> on PyExc_Exception, but that doesn't seem to work. Furthermore I have
>> found
>> various solutions how to translate exceptions thrown in C++ into
>> proper Python
>> exceptions, but in my case these solutions sit at the wrong place.
>
> I've based my code on.
> http://stackoverflow.com/questions/9620268/boost-python-custom-exception-class

I have used the same reference and also this suggestion for including 
the other attributes shown here:
http://stackoverflow.com/questions/11448735/boostpython-export-custom-exception-and-inherit-from-pythons-exception

However, this doesn't solve my problem.
It works fine when I throw the MyException in C++, but when I raise the 
MyCPPException in Python, the translator is not called (which makes 
sense), so the attribute 'cause' does not change.

Actually, before I throw the MyException for the first time in C++, 
MyCPPException does not have the attribute 'cause' at all.

This issue should be the same, if I set the exception with 
PyErr_SetObject, since the translator is not called, when I 'raise' it.


My current attempt is quite different (and all in Python):
import exc

class MyException(Exception):
   def __init__(self, *args):
     self.e = exc.MyException(*args)

   def __getattr__(self, name):
     return self.e.__getattribute__(name)

   def __str__(self):
     return type(self).__name__ + ': ' + self.e.what()

e=MyException(1, 'bla')

I can 'raise MyException(1, 'some error')' and get the attributes I have 
in C++. If the attributes change, it should all work except for the 
__str__ function, which is hardcoded.

The drawback is that it's in python. The python part will be developed 
by third parties and I then have to make sure that they see and use this 
provided exception ...

Also I don't know yet how translating this back to C++ will play out.

I guess I am jumping a bit ahead ... is it correct from me to assume 
that this behaviour is not possible with the solutions posted on 
stackoverflow or am I overlooking something?

I am very happy about any replies :)

Cheers
Martin

>
>
>> I would like to avoid to create a corresponding python class to the C++
>> exception, because there would be added effort to keep the two
>> descriptions
>> consistent.
>
> True.
>
>> class MyException: public std::exception {
>> MyException();
>> MyException(int code, const std::string &string);
>>
>> int code();
>> const char* what();
>>
>> int errorCode;
>> std::string errorMessage;
>> };
>
> The only unusual stuff is that you need both code and message. 2 ideas
> come to mind.
> 1) you can base the python exception not on PyExc_Exception but on a
> custom class which can handle both error code and message, so the
> exception translator can do both a PyErr_SetString and a
> "PyErr_SetCode". This way you can use the exception in both C and Python
> in the same style, no need to keep anything in sync.
>
> 2) you can base the Python exception on the standard PyExc_Exception but
> use PyErr_SetObject in the exception translator. A quick search finds this
> http://stackoverflow.com/questions/2261858/boostpython-export-custom-exception
>
> (does not inherit from Exception, though)
>

-- 
Martin Hellmich                    Information Technology Department
mhellmic at cern.ch                                                CERN
+41 22 76 765 26                                   CH-1211 Geneva 23


More information about the Cplusplus-sig mailing list