6 namespace py = boost::python;
8 using namespace suanzi;
10 static const std::string TAG = "PyWrapper";
12 PyWrapperPtr PyWrapper::getInstance(const string& pydir)
14 LOG_DEBUG(TAG, "getInstance");
15 static PyWrapperPtr instance (new PyWrapper(pydir));
19 PyWrapper::PyWrapper(const std::string& python_dir)
21 LOG_DEBUG(TAG, "Init Python interpreter");
24 main_module = py::import("__main__");
25 main_namespace = main_module.attr("__dict__");
26 py::exec("import sys", main_namespace);
27 std::string cmd = "sys.path.insert(0, '" + python_dir + "')";
28 py::exec(cmd.c_str(), main_namespace);
29 py::exec("import signal", main_namespace);
30 py::exec("signal.signal(signal.SIGINT, signal.SIG_DFL)", main_namespace);
31 } catch (boost::python::error_already_set const &){
32 LOG_ERROR(TAG, "Error in Python: " + parse_python_exception())
36 PyWrapper::~PyWrapper()
39 LOG_DEBUG(TAG, "DeInit Python interpreter");
42 py::object PyWrapper::import(const std::string& module)
44 LOG_DEBUG(TAG, "import " + module);
47 o = py::import(module.c_str());
48 } catch (boost::python::error_already_set const &){
49 LOG_ERROR(TAG, parse_python_exception());
54 void PyWrapper::exec(const std::string& cmd)
57 py::exec(cmd.c_str());
58 } catch(boost::python::error_already_set const &){
59 LOG_ERROR(TAG, parse_python_exception());
64 // refer to http://www.sigverse.org/wiki/en/index.php?Import%20and%20use%20of%20user%20defined%20python%20modules
65 std::string PyWrapper::parse_python_exception(){
66 PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
67 // Fetch the exception info from the Python C API
68 PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
71 std::string ret("Unfetchable Python error");
72 // If the fetch got a type pointer, parse the type into the exception string
74 py::handle<> h_type(type_ptr);
75 py::str type_pstr(h_type);
76 // Extract the string from the boost::python object
77 py::extract<std::string> e_type_pstr(type_pstr);
78 // If a valid string extraction is available, use it
79 // otherwise use fallback
80 if(e_type_pstr.check())
83 ret = "Unknown exception type";
85 // Do the same for the exception value (the stringification of the exception)
86 if(value_ptr != NULL){
87 py::handle<> h_val(value_ptr);
89 py::extract<std::string> returned(a);
91 ret += ": " + returned();
93 ret += std::string(": Unparseable Python error: ");
95 // Parse lines from the traceback using the Python traceback module
96 if(traceback_ptr != NULL){
97 py::handle<> h_tb(traceback_ptr);
98 // Load the traceback module and the format_tb function
99 py::object tb(py::import("traceback"));
100 py::object fmt_tb(tb.attr("format_tb"));
101 // Call format_tb to get a list of traceback strings
102 py::object tb_list(fmt_tb(h_tb));
103 // Join the traceback strings into a single string
104 py::object tb_str(py::str("\n").join(tb_list));
105 // Extract the string, check the extraction, and fallback in necessary
106 py::extract<std::string> returned(tb_str);
108 ret += ": " + returned();
110 ret += std::string(": Unparseable Python traceback");