[C++-sig] Proposal to improve Python exception handling in Boost.Python

Frank Benkstein benkstein at langer-emv.de
Thu Jun 19 10:55:16 CEST 2008


Hi.

Disclaimer:  I'm quite new to Boost.Python, so I might have missed some
things.  If so, please tell me.  Also I'm currently mostly concerned
with embedding, not extending.

When embedding Python with Boost.Python it is currently quite
complicated to handle exceptions originating from Python code.

If a Python error is detected by Boost.Python, error_already_set is
thrown.  Handling the original Python exception from C++ is cumbersome:

<code>
using namespace boost::python;

try {
  object value = some_dict["key"];
  ...
} catch (error_already_set &) {
  if (PyErr_ExceptionMatches(PyExc_KeyError) {
    // Do actual exception handling
    ...
  } else {
    // We can't just rethrow the exception because that would terminate
    // the program.
    PyErr_Print();
    ...
  }
}
</code>

I would like to see at least the Python standard exceptions [1] to be
translated to C++ exceptions by Boost.Python (possibly in the
boost::python::exceptions namespace - mirroring the Python exceptions
module) so the previous code could be written as follows:

<code>
using namespace boost::python;

try {
  object value = some_dict["key"];
  ...
} catch (exceptions::key_error &e) {
  BOOST_ASSERT(e.args() == make_tuple("key"));
  // Do actual exception handling
  ...
} catch (exceptions::base_exception &e) {
  std::cerr << e.traceback << std::flush;
  std::cerr << e << e.flush;
}
</code>

Those exceptions could be automatically translated back to the original
Python exceptions and the traceback restored (using PyErr_Restore).

If you (the Boost.Python developers) agree to this proposal I would like
to submit patches implementing the mentioned functionality through the
following steps:

1. Convert all sites throwing error_already_set or calling
   throw_error_already_set to calls to handle_python_exception.
   handle_python_exception would just call throw_error_already_set
   itself.
2. Provide a registry for functions to be called when a specific Python
   exception is encountered.  These functions get called with three
   boost::python::object arguments, the exception type, value and the
   traceback object when an exception is detected by
   handle_python_exception.  As a fallback if no matching function is
   found error_already_set would still be thrown.
3. Provide a new namespace boost::python::exceptions with C++ exceptions
   that correspond to the Python standard exceptions[1] including
   inheritance.  Each class should have a static boost::python::object
   member "mapped_type" wrapping the Python type object.  And instance
   members "type", "value" and "traceback" so it can be set or restored
   as the Python error indicator using PyErr_Restore or PyErr_SetObject
   if the traceback is None.
4. Register all exceptions from 3. with the mechanism from 2.  Remove
   the fallback throwing error_already_set from handle_python_exception
   because base_exception would match all unknown exceptions.
   Provide a runtime switch that would make handle_python_exception
   either use either the registry from 2. or just throw
   error_already_set.  This is necessary to be compatible to code that
   is depending on error_already_set.  I think it is safe to assume that
   this switch is guarded by the GIL and therefore thread safe.

As you have probably noticed 3. and 4. will only work with Python >=
2.5.  I don't think this is a problem, though, as there could be a
simple compile switch around those features.  Code that has to be
compatible with older versions of python can still use the exception
handling registry from 2.  If need be 3. and 4. can also be adapted to
work with older versions of Python but that is currently not important
to me.

Best regards,
Frank Benkstein.

[1] http://docs.python.org/api/standardExceptions.html

-- 
Frank Benkstein

Software Development

Tel.: +49(0) 351 430093-27
Fax : +49(0) 351 430093-22

mailto:benkstein at langer-emv.de

Langer EMV-Technik GmbH
D-01728 Bannewitz
Nöthnitzer Hang 31
Germany

Registergericht: Amtsgericht Dresden, HRB 15402
Geschäftsführer: Gunter Langer

www.langer-emv.de


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080619/1a5730d3/attachment.pgp>


More information about the Cplusplus-sig mailing list