[C++-sig] bad exception conversion

Niall Douglas s_sourceforge at nedprod.com
Thu Jun 14 14:33:26 CEST 2012


Do you think that this answer is worth adding to the BPL FAQ? 
Normally you don't need to derive from Python's Exception object, and 
indeed in my own custom exception implementations I never did so. 
However, if this has changed, an FAQ entry is appropriate.

Ideally, a wishlist work item would map std::exception onto Python's 
Exception, so if you inherit from std::exception it appears as 
Python's Exception. I was just reading last night in Nicolai 
Josuttis' C++11 updated "The C++ Standard Library" how very much 
easier this has become to implement in C++11. The only fault with 
that book so far is it makes me want to dump old compilers right now.

Niall

On 13 Jun 2012 at 19:02, Jim Bosch wrote:

> On 06/13/2012 06:31 AM, Wichert Akkerman wrote:
> > I have some glue code that calls a C++ function which can raise an
> > unsuitable_error exception. I have an exception translator which will
> > convert that to a more pythonic version (UnsuitableError), but when I
> > use that I get an "SystemError: 'finally' pops bad exception" error on
> > the python side. As far as I can see my code looks correct, but I
> > suspect I am overlooking something trivial somewhere.
> >
> >
> > using namespace boost::python;
> >
> > class UnsuitableError : public std::exception {
> > public:
> >      UnsuitableError() : reasons() { }
> >      ~UnsuitableError() throw() {}
> >      boost::python::list reasons;
> > };
> >
> > namespace {
> >      PyObject *UnsuitableErrorType = NULL;
> >
> >      void translator(const unsuitable_error &e) {
> >          std::list<const char*>::const_iterator i;
> >          PyObject* unicode;
> >          UnsuitableError error=UnsuitableError();
> >          for (i=e.reasons.begin(); i!=e.reasons.end(); i++) {
> >              unicode = PyUnicode_FromString(*i);
> > error.reasons.append(boost::python::object(boost::python::handle<>(unicode)));
> >
> >          }
> >
> >          boost::python::object exc(error);
> >          PyErr_SetObject(UnsuitableErrorType, exc.ptr());
> >      }
> > }
> >
> >
> > void export() {
> >      object
> > module(handle<>(borrowed(PyImport_AddModule("mypkg.article"))));
> >      scope().attr("article")=module;
> >      scope module_scope = module;
> >
> >      class_<UnsuitableError> UnsuitableErrorClass("UnsuitableError");
> >      UnsuitableErrorClass.def_readonly("reasons",
> > &UnsuitableError::reasons);
> >      UnsuitableErrorType=UnsuitableErrorClass.ptr();
> >
> >      register_exception_translator<unsuitable_error>(&translator);
> > }
> 
> I suspect the problem is that your custom exception doesn't derived from 
> Python's built-in Exception base class.  Unfortunately, it's impossible 
> to do that with a Boost.Python wrapped class, but you can get it all 
> done with the Python C API:
> 
> namespace {
>      PyObject *UnsuitableErrorType = NULL;
> 
>      void translator(const unsuitable_error &e) {
>          std::list<const char*>::const_iterator i;
>          PyObject* unicode;
> 	boost::python::list reasons;
>          for (i=e.reasons.begin(); i!=e.reasons.end(); i++) {
>              boost::python::handle<> unicode(PyUnicode_FromString(*i));
>              reasons.append(boost::python::object(unicode));
>          }
>          boost::python::handle<> error(
>              PyObject_CallFunctionObjArgs(
>                  UnsuitableErrorType, NULL
>              )
>          );
>          PyObject_SetAttrString(error.get(), "reasons", reasons.get());
>          PyErr_SetObject(UnsuitableErrorType, error.get());
>      }
> }
> 
> 
> void export() {
>      object module(handle<>(borrowed(PyImport_AddModule("mypkg.article"))));
>      scope().attr("article")=module;
>      scope module_scope = module;
> 
>      // NOTE: can use something other than RuntimeError for base class
>      UnsuitableErrorType = PyErr_NewException(
>          "UnsuitableError", PyExc_RuntimeError, NULL
>      );
>      module_scope.attr("UnsuitableError") =
>          object(handle<>(borrowed(UnsuitableErrorType)));
> 
>      register_exception_translator<unsuitable_error>(&translator);
> }
> 
> 
> I haven't tested any of that, but hopefully it's close enough to point 
> you in the right direction.
> 
> 
> Jim
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig


-- 
Technology & Consulting Services - ned Productions Limited.
http://www.nedproductions.biz/. VAT reg: IE 9708311Q.
Work Portfolio: http://careers.stackoverflow.com/nialldouglas/


More information about the Cplusplus-sig mailing list