X-Git-Url: http://47.100.26.94:8080/?a=blobdiff_plain;ds=sidebyside;f=src%2FPyWrapper.cpp;fp=src%2FPyWrapper.cpp;h=e19fe3d32196dedf35be44cff4c81d88bf73f082;hb=81741fb5b3fe86bf29a130f367ea102e3aa99b0b;hp=0000000000000000000000000000000000000000;hpb=70532232dd98f31467eff7baaaff6e68f803bb45;p=trackerpp.git diff --git a/src/PyWrapper.cpp b/src/PyWrapper.cpp new file mode 100644 index 0000000..e19fe3d --- /dev/null +++ b/src/PyWrapper.cpp @@ -0,0 +1,113 @@ +#include "PyWrapper.h" +#include +#include +#include "Logger.h" + +namespace py = boost::python; +using namespace std; +using namespace suanzi; + +static const std::string TAG = "PyWrapper"; + +PyWrapperPtr PyWrapper::getInstance(const string& pydir) +{ + LOG_DEBUG(TAG, "getInstance"); + static PyWrapperPtr instance (new PyWrapper(pydir)); + return instance; +} + +PyWrapper::PyWrapper(const std::string& python_dir) +{ + LOG_DEBUG(TAG, "Init Python interpreter"); + Py_Initialize(); + try{ + main_module = py::import("__main__"); + main_namespace = main_module.attr("__dict__"); + py::exec("import sys", main_namespace); + std::string cmd = "sys.path.insert(0, '" + python_dir + "')"; + py::exec(cmd.c_str(), main_namespace); + py::exec("import signal", main_namespace); + py::exec("signal.signal(signal.SIGINT, signal.SIG_DFL)", main_namespace); + } catch (boost::python::error_already_set const &){ + LOG_ERROR(TAG, "Error in Python: " + parse_python_exception()) + } +} + +PyWrapper::~PyWrapper() +{ + Py_Finalize(); + LOG_DEBUG(TAG, "DeInit Python interpreter"); +} + +py::object PyWrapper::import(const std::string& module) +{ + LOG_DEBUG(TAG, "import " + module); + py::object o; + try{ + o = py::import(module.c_str()); + } catch (boost::python::error_already_set const &){ + LOG_ERROR(TAG, parse_python_exception()); + } + return o; +} + +void PyWrapper::exec(const std::string& cmd) +{ + try{ + py::exec(cmd.c_str()); + } catch(boost::python::error_already_set const &){ + LOG_ERROR(TAG, parse_python_exception()); + } +} + + +// refer to http://www.sigverse.org/wiki/en/index.php?Import%20and%20use%20of%20user%20defined%20python%20modules +std::string PyWrapper::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 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 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 returned(tb_str); + if(returned.check()) + ret += ": " + returned(); + else + ret += std::string(": Unparseable Python traceback"); + } + return ret; +}