20 #ifdef FLOW123D_HAVE_PYTHON 34 string python_sys_path = R
"CODE( 39 # print('\n'.join(sys.path)) 40 return os.pathsep.join(sys.path) 45 string PythonLoader::sys_path =
"";
48 void PythonLoader::initialize(
const std::string &python_home)
50 static internal::PythonRunning _running(python_home);
54 PyObject * PythonLoader::load_module_from_file(
const std::string& fname) {
58 std::ifstream file_stream;
61 file_stream.exceptions ( ifstream::failbit | ifstream::badbit );
63 std::stringstream buffer;
64 buffer << file_stream.rdbuf();
67 std::size_t pos = fname.rfind(
"/");
68 if (pos != string::npos)
69 module_name = fname.substr(pos+1);
76 return load_module_from_string(module_name, buffer.str() );
81 PyObject * PythonLoader::load_module_from_string(
const std::string& module_name,
const std::string& source_string) {
84 PyObject * compiled_string = Py_CompileString(source_string.c_str(), module_name.c_str(), Py_file_input);
85 PythonLoader::check_error();
88 PyObject * result = PyImport_ExecCodeModule(module_name.c_str(), compiled_string);
89 PythonLoader::check_error();
93 PyObject * PythonLoader::load_module_by_name(
const std::string& module_name) {
97 PyObject * module_object = PyImport_ImportModule (module_name.c_str());
98 PythonLoader::check_error();
100 return module_object;
104 void PythonLoader::check_error() {
105 if (PyErr_Occurred()) {
106 PyObject *ptype, *pvalue, *ptraceback;
107 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
108 string error_description = string(PyUnicode_AsUTF8(PyObject_Str(pvalue)));
114 PyObject *traceback_module = PyImport_ImportModule(
"traceback");
116 string str_traceback;
117 if (traceback_module && ptraceback) {
118 PyObject *format_tb_method = PyObject_GetAttrString(traceback_module,
"format_tb");
119 if (format_tb_method) {
120 PyObject * traceback_lines = PyObject_CallFunctionObjArgs(format_tb_method, ptraceback, NULL);
121 if (traceback_lines) {
122 PyObject * join_str = PyUnicode_FromString(
"");
123 PyObject * join = PyObject_GetAttrString(join_str,
"join");
124 PyObject * message = PyObject_CallFunctionObjArgs(join, traceback_lines, NULL);
126 str_traceback = string(PyUnicode_AsUTF8(PyObject_Str(message)));
128 Py_DECREF(traceback_lines);
137 string python_path = PythonLoader::sys_path;
138 replace(python_path.begin(), python_path.end(),
':',
'\n');
142 "\nType: " + string(PyUnicode_AsUTF8(PyObject_Str(ptype))) +
"\n" 143 +
"Message: " + string(PyUnicode_AsUTF8(PyObject_Str(pvalue))) +
"\n" 144 +
"Traceback: \n" + str_traceback +
"\n" 145 +
"Paths: " +
"\n" + python_path +
"\n";
147 THROW(ExcPythonError() << EI_PythonMessage( py_message ));
153 PyObject * PythonLoader::get_callable(PyObject *module,
const std::string &func_name) {
154 char func_char[func_name.size()+2];
155 strcpy(func_char, func_name.c_str());
156 PyObject * func = PyObject_GetAttrString(module, func_char );
157 PythonLoader::check_error();
159 if (! PyCallable_Check(func)) {
161 ss <<
"Field '" << func_name <<
"' from the python module: " << PyModule_GetName(module) <<
" is not callable." << endl;
162 THROW(ExcPythonError() << EI_PythonMessage( ss.str() ));
170 wstring to_py_string(
const string &str) {
171 wchar_t wbuff[ str.size() ];
172 size_t wstr_size = mbstowcs( wbuff, str.c_str(), str.size() );
173 return wstring( wbuff, wstr_size );
176 string from_py_string(
const wstring &wstr) {
177 char buff[ wstr.size() ];
178 size_t str_size = wcstombs( buff, wstr.c_str(), wstr.size() );
179 return string( buff, str_size );
182 #define STR_EXPAND(tok) #tok 183 #define STR(tok) string(STR_EXPAND(tok)) 187 PythonRunning::PythonRunning(
const std::string& program_name)
189 #ifdef FLOW123D_PYTHON_PREFIX 190 static wstring _python_program_name = to_py_string(program_name);
191 Py_SetProgramName( &(_python_program_name[0]) );
192 wstring full_program_name = Py_GetProgramFullPath();
198 size_t pos = full_program_name.rfind( to_py_string(
"flow123d") );
199 wstring full_flow_prefix =
".";
200 if (pos != wstring::npos) {
201 full_flow_prefix = full_program_name.substr(0,pos-
string(
"/bin/").size() );
204 wstring default_py_prefix(to_py_string(STR(FLOW123D_PYTHON_PREFIX)));
207 static wstring our_py_home(full_flow_prefix +
":" +default_py_prefix);
208 Py_SetPythonHome( &(our_py_home[0]) );
212 #endif //FLOW123D_PYTHON_PREFIX 217 #ifdef FLOW123D_PYTHON_EXTRA_MODULES_PATH 220 wstring path = Py_GetPath();
221 path = path + to_py_string(
":") + to_py_string(
string(FLOW123D_PYTHON_EXTRA_MODULES_PATH));
222 PySys_SetPath (path.c_str());
225 #endif //FLOW123D_PYTHON_EXTRA_MODULES_PATH 228 PyObject *moduleMain = PyImport_ImportModule(
"__main__");
229 PyRun_SimpleString(python_sys_path.c_str());
230 PyObject *func = PyObject_GetAttrString(moduleMain,
"get_paths");
231 PyObject *args = PyTuple_New (0);
232 PyObject *result = PyObject_CallObject(func, args);
233 PythonLoader::check_error();
236 PythonLoader::sys_path = string(PyUnicode_AsUTF8(result));
241 PythonRunning::~PythonRunning() {
247 #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.