20 #ifdef FLOW123D_HAVE_PYTHON 33 string python_sys_path = R
"CODE( 38 # print('\n'.join(sys.path)) 39 return os.pathsep.join(sys.path) 44 string PythonLoader::sys_path =
"";
47 void PythonLoader::initialize(
const std::string &python_home)
49 static internal::PythonRunning _running(python_home);
53 PyObject * PythonLoader::load_module_from_file(
const std::string& fname) {
57 std::ifstream file_stream;
60 file_stream.exceptions ( ifstream::failbit | ifstream::badbit );
62 std::stringstream buffer;
63 buffer << file_stream.rdbuf();
66 unsigned int pos = fname.rfind(
"/");
67 if (pos != string::npos)
68 module_name = fname.substr(pos+1);
75 return load_module_from_string(module_name, buffer.str() );
80 PyObject * PythonLoader::load_module_from_string(
const std::string& module_name,
const std::string& source_string) {
83 PyObject * compiled_string = Py_CompileString(source_string.c_str(), module_name.c_str(), Py_file_input);
84 PythonLoader::check_error();
87 PyObject * result = PyImport_ExecCodeModule(module_name.c_str(), compiled_string);
88 PythonLoader::check_error();
92 PyObject * PythonLoader::load_module_by_name(
const std::string& module_name) {
96 PyObject * module_object = PyImport_ImportModule (module_name.c_str());
97 PythonLoader::check_error();
103 void PythonLoader::check_error() {
104 if (PyErr_Occurred()) {
105 PyObject *ptype, *pvalue, *ptraceback;
106 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
107 string error_description = string(PyUnicode_AsUTF8(PyObject_Str(pvalue)));
113 PyObject *traceback_module = PyImport_ImportModule(
"traceback");
115 string str_traceback;
116 if (traceback_module && ptraceback) {
117 PyObject *format_tb_method = PyObject_GetAttrString(traceback_module,
"format_tb");
118 if (format_tb_method) {
119 PyObject * traceback_lines = PyObject_CallFunctionObjArgs(format_tb_method, ptraceback, NULL);
120 if (traceback_lines) {
121 PyObject * join_str = PyUnicode_FromString(
"");
122 PyObject * join = PyObject_GetAttrString(join_str,
"join");
123 PyObject * message = PyObject_CallFunctionObjArgs(join, traceback_lines, NULL);
125 str_traceback = string(PyUnicode_AsUTF8(PyObject_Str(message)));
127 Py_DECREF(traceback_lines);
136 string python_path = PythonLoader::sys_path;
137 replace(python_path.begin(), python_path.end(),
':',
'\n');
141 "\nType: " + string(PyUnicode_AsUTF8(PyObject_Str(ptype))) +
"\n" 142 +
"Message: " + string(PyUnicode_AsUTF8(PyObject_Str(pvalue))) +
"\n" 143 +
"Traceback: \n" + str_traceback +
"\n" 144 +
"Paths: " +
"\n" + python_path +
"\n";
146 THROW(ExcPythonError() << EI_PythonMessage( py_message ));
152 PyObject * PythonLoader::get_callable(PyObject *module,
const std::string &func_name) {
153 char func_char[func_name.size()+2];
154 strcpy(func_char, func_name.c_str());
155 PyObject * func = PyObject_GetAttrString(module, func_char );
156 PythonLoader::check_error();
158 if (! PyCallable_Check(func)) {
160 ss <<
"Field '" << func_name <<
"' from the python module: " << PyModule_GetName(module) <<
" is not callable." << endl;
161 THROW(ExcPythonError() << EI_PythonMessage( ss.str() ));
169 wstring to_py_string(
const string &str) {
170 wchar_t wbuff[ str.size() ];
171 size_t wstr_size = mbstowcs( wbuff, str.c_str(), str.size() );
172 return wstring( wbuff, wstr_size );
175 string from_py_string(
const wstring &wstr) {
176 char buff[ wstr.size() ];
177 size_t str_size = wcstombs( buff, wstr.c_str(), wstr.size() );
178 return string( buff, str_size );
181 #define STR_EXPAND(tok) #tok 182 #define STR(tok) string(STR_EXPAND(tok)) 186 PythonRunning::PythonRunning(
const std::string& program_name)
188 #ifdef FLOW123D_PYTHON_PREFIX 189 static wstring _python_program_name = to_py_string(program_name);
190 Py_SetProgramName( &(_python_program_name[0]) );
191 wstring full_program_name = Py_GetProgramFullPath();
197 size_t pos = full_program_name.rfind( to_py_string(
"flow123d") );
198 wstring full_flow_prefix =
".";
199 if (pos != wstring::npos) {
200 full_flow_prefix = full_program_name.substr(0,pos-
string(
"/bin/").size() );
203 wstring default_py_prefix(to_py_string(STR(FLOW123D_PYTHON_PREFIX)));
206 static wstring our_py_home(full_flow_prefix +
":" +default_py_prefix);
207 Py_SetPythonHome( &(our_py_home[0]) );
209 #endif //FLOW123D_PYTHON_PREFIX 214 #ifdef FLOW123D_PYTHON_EXTRA_MODULES_PATH 217 wstring path = Py_GetPath();
218 path = path + to_py_string(
":") + to_py_string(
string(FLOW123D_PYTHON_EXTRA_MODULES_PATH));
219 PySys_SetPath (path.c_str());
222 #endif //FLOW123D_PYTHON_EXTRA_MODULES_PATH 225 PyObject *moduleMain = PyImport_ImportModule(
"__main__");
226 PyRun_SimpleString(python_sys_path.c_str());
227 PyObject *func = PyObject_GetAttrString(moduleMain,
"get_paths");
228 PyObject *args = PyTuple_New (0);
229 PyObject *result = PyObject_CallObject(func, args);
230 PythonLoader::check_error();
233 PythonLoader::sys_path = string(PyUnicode_AsUTF8(result));
238 PythonRunning::~PythonRunning() {
244 #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.