Skip to content

Instantly share code, notes, and snippets.

Created November 18, 2013 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/7537252 to your computer and use it in GitHub Desktop.
Save anonymous/7537252 to your computer and use it in GitHub Desktop.
#include <boost/python.hpp>
#include <Python.h>
#include <iostream>
using namespace std;
namespace py = boost::python;
std::string parse_python_exception(){
PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
// Fetch the exception info from the Python C API
PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
// Fallback error
std::string ret("Unfetchable Python error");
// If the fetch got a type pointer, parse the type into the exception string
if(type_ptr != NULL){
py::handle<> h_type(type_ptr);
py::str type_pstr(h_type);
// Extract the string from the boost::python object
py::extract<std::string> e_type_pstr(type_pstr);
// If a valid string extraction is available, use it
// otherwise use fallback
if(e_type_pstr.check())
ret = e_type_pstr();
else
ret = "Unknown exception type";
}
// Do the same for the exception value (the stringification of the exception)
if(value_ptr != NULL){
py::handle<> h_val(value_ptr);
py::str a(h_val);
py::extract<std::string> returned(a);
if(returned.check())
ret += ": " + returned();
else
ret += std::string(": Unparseable Python error: ");
}
// Parse lines from the traceback using the Python traceback module
if(traceback_ptr != NULL){
py::handle<> h_tb(traceback_ptr);
// Load the traceback module and the format_tb function
py::object tb(py::import("traceback"));
py::object fmt_tb(tb.attr("format_tb"));
// Call format_tb to get a list of traceback strings
py::object tb_list(fmt_tb(h_tb));
// Join the traceback strings into a single string
py::object tb_str(py::str("\n").join(tb_list));
// Extract the string, check the extraction, and fallback in necessary
py::extract<std::string> returned(tb_str);
if(returned.check())
ret += ": " + returned();
else
ret += std::string(": Unparseable Python traceback");
}
return ret;
}
void getServices(vector<pair<string, string> > & ret) {
try {
Py_Initialize();
char* argv = (char*) "";
PySys_SetArgv(0, &argv);
py::object main_module = py::import("__main__");
// load the dictionary object out of the main module
py::object main = main_module.attr("__dict__");
// load functions
py::exec("import rosservice", main);
py::object get_service_list = py::eval("rosservice.get_service_list", main);
py::object get_service_type = py::eval("rosservice.get_service_type", main);
// do look-ups
py::object srv_list = get_service_list();
for(int i=0; i<py::len(srv_list); i++) {
std::string s = py::extract<std::string>(srv_list[i]);
py::object t_obj = get_service_type(s);
std::string t = py::extract<std::string>(t_obj);
ret.emplace_back(s,t);
}
} catch(py::error_already_set const&) {
string perror_str = parse_python_exception();
cout << "Error in Python: " << perror_str << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment