[Boost-bugs] [Boost C++ Libraries] #2781: Add python exception info extractor

Subject: [Boost-bugs] [Boost C++ Libraries] #2781: Add python exception info extractor
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-02-19 13:54:30


#2781: Add python exception info extractor
--------------------------+-------------------------------------------------
 Reporter: macke_at_[hidden] | Owner: dave
     Type: Patches | Status: new
Milestone: Boost 1.39.0 | Component: Python
  Version: Boost 1.38.0 | Severity: Not Applicable
 Keywords: |
--------------------------+-------------------------------------------------
 Something like this is useful when embedding python, and it took me almost
 an entire day to figure out how to do this. (Having not used boost::python
 before, I got many crashes when trying to extract data again.)

 Example:
 {{{
     try {
         boost::python::eval(...);
     } catch (boost::python::error_already_set&) {
         std::string msg = handle_pyerror();
         std::cerr << "Error runnin python code: " << msg;
     }
 }}}

 Implementation:

 {{{
 #!cpp
 std::string handle_pyerror()
 {
     using namespace boost::python;

     std::ostringstream os;
     os << "Python error:\n " << std::flush;

     PyObject *type = 0, *val = 0, *tb = 0;
     PyErr_Fetch(&type, &val, &tb);
     handle<> e_val(val), e_type(type), e_tb(allow_null(tb));

     try {
         object t = extract<object>(e_type.get());
         object t_name = t.attr("__name__");
         std::string typestr = extract<std::string>(t_name);

         os << typestr << std::flush;
     } catch (error_already_set const &) {
         os << "Internal error getting error type:\n";
         PyErr_Print();
     }

     os << ": ";

     try {
         object v = extract<object>(e_val.get());
         std::string valuestr = extract<std::string>(v.attr("__str__")());
         os << valuestr << std::flush;
     } catch (error_already_set const &) {
         os << "Internal error getting value type:\n";
         PyErr_Print();
     }

     if (tb) {
         try {
             object tb_list = import("traceback").attr("format_tb")(e_tb);
             object tb_str = str("").attr("join")(tb_list);
             std::string str = extract<std::string>(tb_str);

             os << "\nTraceback (recent call last):\n" << str;
         } catch (error_already_set const &) {
             os << "Internal error getting traceback:\n";
             PyErr_Print();
         }
     } else {
         os << std::endl;
     }

     return os.str();
 }
 }}}

 I'm sure it could be done better, but I'm sure this would help quite a
 bit.

 A wrapper for all python calls that translated python errors into
 C++-exceptions with proper contents would be very nice, but I can live
 with this.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/2781>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:59 UTC