Flow123d
python_loader.cc
Go to the documentation of this file.
1 /*
2  * python_loader.cc
3  *
4  * Created on: Aug 31, 2012
5  * Author: jb
6  */
7 
8 
9 #ifdef HAVE_PYTHON
10 
11 #include "system/python_loader.hh"
12 #include "global_defs.h"
13 #include "system/system.hh"
14 #include <string>
15 #include <iostream>
16 #include <fstream>
17 #include <sstream>
18 
19 void PythonLoader::initialize(const std::string &python_home)
20 {
21  static internal::PythonRunning _running(python_home);
22 }
23 
24 
25 PyObject * PythonLoader::load_module_from_file(const std::string& fname) {
26  initialize();
27 
28  // don't know direct way how to load module form file, so we read it into string and use load_module_from_string
29  std::ifstream file_stream( fname.c_str() );
30  // check correct openning
31  INPUT_CHECK(! file_stream.fail(), "Can not open input file '%s'.\n", fname.c_str() );
32  file_stream.exceptions ( ifstream::failbit | ifstream::badbit );
33 
34  std::stringstream buffer;
35  buffer << file_stream.rdbuf();
36 
37  string module_name;
38  unsigned int pos = fname.rfind("/");
39  if (pos != string::npos)
40  module_name = fname.substr(pos+1);
41  else
42  module_name = fname;
43 
44  // cout << "python module: " << module_name <<endl;
45  // DBGMSG("%s\n", buffer.str().c_str());
46  // TODO: use exceptions and catch it here to produce shorter and more precise error message
47  return load_module_from_string(module_name, buffer.str() );
48 }
49 
50 
51 
52 PyObject * PythonLoader::load_module_from_string(const std::string& module_name, const std::string& source_string) {
53  initialize();
54 
55  // for unknown reason module name is non-const, so we have to make char * copy
56  char * tmp_name = new char[ module_name.size() + 2 ];
57  strcpy( tmp_name, module_name.c_str() );
58  PyObject * result = PyImport_ExecCodeModule(tmp_name,
59  Py_CompileString( source_string.c_str(), "flow123d_python_loader", Py_file_input ) );
60 
61  if (result == NULL) {
62  PyErr_Print();
63  std::cerr << "Error: Can not load python module '" << module_name << "' from string:" << std::endl;
64  std::cerr << source_string << std::endl;
65  }
66 
67  delete[] tmp_name;
68  return result;
69 }
70 
71 
72 
73 namespace internal {
74 
75 PythonRunning::PythonRunning(const std::string& python_home)
76 {
77  /*
78  * Possibly set alternative path to non-library part of Python.
79  * This is necessary for release builds.
80  */
81  if (python_home != "") {
82  static string _python_home_storage = python_home; // permanent non-const storage required
83  //Py_SetPythonHome( &(_python_home_storage[0]) );
84  //Py_SetPythonHome( ".." );
85  Py_SetProgramName( &(_python_home_storage[0]) );
86  std::cout << Py_GetPath() << std::endl;
87  }
88  Py_Initialize();
89 }
90 
91 
92 
93 PythonRunning::~PythonRunning() {
94  Py_Finalize();
95 }
96 
97 } // close namespace internal
98 
99 #endif // HAVE_PYTHON