20 #ifdef FLOW123D_HAVE_PYTHON 33 string python_sys_path = R
"CODE( 38 return os.pathsep.join(sys.path) 43 string PythonLoader::sys_path =
"";
45 void PythonLoader::initialize(
const std::string &python_home)
47 static internal::PythonRunning _running(python_home);
51 PyObject * PythonLoader::load_module_from_file(
const std::string& fname) {
55 std::ifstream file_stream;
58 file_stream.exceptions ( ifstream::failbit | ifstream::badbit );
60 std::stringstream buffer;
61 buffer << file_stream.rdbuf();
64 unsigned int pos = fname.rfind(
"/");
65 if (pos != string::npos)
66 module_name = fname.substr(pos+1);
73 return load_module_from_string(module_name, buffer.str() );
78 PyObject * PythonLoader::load_module_from_string(
const std::string& module_name,
const std::string& source_string) {
82 char * tmp_name =
new char[ module_name.size() + 2 ];
83 strcpy( tmp_name, module_name.c_str() );
85 PyObject * compiled_string = Py_CompileString( source_string.c_str(), module_name.c_str(), Py_file_input );
86 if (PyErr_Occurred()) {
87 PyObject *ptype, *pvalue, *ptraceback, *pystr;
88 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
90 if ( !PyString_Check(pvalue) ) {
92 PyObject* err_type = PySequence_GetItem(pvalue, 0);
93 pystr = PyObject_Str(err_type);
94 ss << PyString_AsString(pystr) << endl;
95 PyObject* descr = PySequence_GetItem(pvalue, 1);
96 PyObject* file = PySequence_GetItem(descr, 0);
97 pystr = PyObject_Str(file);
98 ss <<
" File \"" << PyString_AsString(pystr) <<
"\"";
99 PyObject* row = PySequence_GetItem(descr, 1);
100 pystr = PyObject_Str(row);
101 ss <<
", line " << PyString_AsString(pystr) << endl;
102 PyObject*
line = PySequence_GetItem(descr, 3);
103 pystr = PyObject_Str(line);
104 ss << PyString_AsString(pystr);
105 PyObject* col = PySequence_GetItem(descr, 2);
106 pystr = PyObject_Str(col);
107 int pos = atoi( PyString_AsString(pystr) );
108 ss << setw(pos) <<
"^" << endl;
109 THROW(ExcPythonError() << EI_PythonMessage( ss.str() ));
111 THROW(ExcPythonError() << EI_PythonMessage( PyString_AsString(pvalue) ));
115 PyObject * result = PyImport_ExecCodeModule(tmp_name, compiled_string);
116 PythonLoader::check_error();
122 PyObject * PythonLoader::load_module_by_name(
const std::string& module_name) {
126 PyObject * module_object = PyImport_ImportModule (module_name.c_str());
127 PythonLoader::check_error();
129 return module_object;
133 void PythonLoader::check_error() {
134 if (PyErr_Occurred()) {
135 PyObject *ptype, *pvalue, *ptraceback;
137 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
138 string error_description = string(PyString_AsString(PyObject_Str(pvalue)));
141 PyObject *module_name = PyString_FromString(
"traceback");
142 PyObject *pyth_module = PyImport_Import(module_name);
143 Py_DECREF(module_name);
145 string str_traceback;
147 PyObject *pyth_func = PyObject_GetAttrString(pyth_module,
"format_exception");
148 if (pyth_func && PyCallable_Check(pyth_func)) {
149 PyObject *pyth_val = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
151 str_traceback = string(PyString_AsString(PyObject_Str(pyth_val)));
158 string python_path = PythonLoader::sys_path;
159 replace(python_path.begin(), python_path.end(),
':',
'\n');
162 "\nType: " + string(PyString_AsString(PyObject_Str(ptype))) +
"\n" 163 +
"Message: " + string(PyString_AsString(PyObject_Str(pvalue))) +
"\n" 164 +
"Traceback: " + str_traceback +
"\n" 165 +
"Paths: " +
"\n" + python_path +
"\n";
167 THROW(ExcPythonError() << EI_PythonMessage( py_message ));
173 PyObject * PythonLoader::get_callable(PyObject *module,
const std::string &func_name) {
174 char func_char[func_name.size()+2];
175 strcpy(func_char, func_name.c_str());
176 PyObject * func = PyObject_GetAttrString(module, func_char );
177 PythonLoader::check_error();
179 if (! PyCallable_Check(func)) {
181 ss <<
"Field '" << func_name <<
"' from the python module: " << PyModule_GetName(module) <<
" is not callable." << endl;
182 THROW(ExcPythonError() << EI_PythonMessage( ss.str() ));
190 wstring to_py_string(
const string &str) {
191 wchar_t wbuff[ str.size() ];
192 size_t wstr_size = mbstowcs( wbuff, str.c_str(), str.size() );
193 return wstring( wbuff, wstr_size );
196 string from_py_string(
const wstring &wstr) {
197 char buff[ wstr.size() ];
198 size_t str_size = wcstombs( buff, wstr.c_str(), wstr.size() );
199 return string( buff, str_size );
204 #if FLOW123D_PYTHONLIBS_VERSION_MAJOR<3 205 #define to_py_string string 206 #define from_py_string string 207 #define PY_STRING string 209 #define PY_STRING wstring 212 #define STR_EXPAND(tok) #tok 213 #define STR(tok) string(STR_EXPAND(tok)) 217 PythonRunning::PythonRunning(
const std::string& program_name)
219 #ifdef FLOW123D_PYTHON_PREFIX 220 static PY_STRING _python_program_name = to_py_string(program_name);
221 Py_SetProgramName( &(_python_program_name[0]) );
222 PY_STRING full_program_name = Py_GetProgramFullPath();
228 size_t pos = full_program_name.rfind( to_py_string(
"flow123d") );
229 PY_STRING full_flow_prefix =
".";
230 if (pos != PY_STRING::npos) {
231 full_flow_prefix = full_program_name.substr(0,pos-
string(
"/bin/").size() );
234 PY_STRING default_py_prefix(to_py_string(STR(FLOW123D_PYTHON_PREFIX)));
237 static PY_STRING our_py_home(full_flow_prefix +
":" +default_py_prefix);
238 Py_SetPythonHome( &(our_py_home[0]) );
306 #endif //FLOW123D_PYTHON_PREFIX 311 #ifdef FLOW123D_PYTHON_EXTRA_MODULES_PATH 314 std::string path = Py_GetPath();
315 path = path +
":" + std::string(FLOW123D_PYTHON_EXTRA_MODULES_PATH);
317 char * path_char =
const_cast<char *
>(path.c_str());
318 PySys_SetPath (path_char);
321 #endif //FLOW123D_PYTHON_EXTRA_MODULES_PATH 324 PyObject *moduleMainString = PyString_FromString(
"__main__");
325 PyObject *moduleMain = PyImport_Import(moduleMainString);
326 PyRun_SimpleString(python_sys_path.c_str());
327 PyObject *func = PyObject_GetAttrString(moduleMain,
"get_paths");
328 PyObject *args = PyTuple_New (0);
329 PyObject *result = PyObject_CallObject(func, args);
330 PythonLoader::check_error();
333 PythonLoader::sys_path = string(PyString_AsString(result));
338 PythonRunning::~PythonRunning() {
344 #endif // FLOW123D_HAVE_PYTHON
void open_stream(Stream &stream) const
Global macros to enhance readability and debugging, general constants.
Dedicated class for storing path to input and output files.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.