Created
November 18, 2013 23:26
-
-
Save anonymous/7537252 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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