1 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 2 3 /* ---------------------------------------------------------------- */ 4 5 #if !defined(PETSC_PYTHON_EXE) 6 #define PETSC_PYTHON_EXE "python" 7 #endif 8 9 static PetscErrorCode PetscPythonFindExecutable(char pythonexe[PETSC_MAX_PATH_LEN]) 10 { 11 PetscBool flag; 12 PetscErrorCode ierr; 13 14 PetscFunctionBegin; 15 /* get the path for the Python interpreter executable */ 16 ierr = PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 17 ierr = PetscOptionsGetString(NULL,NULL,"-python",pythonexe,PETSC_MAX_PATH_LEN,&flag);CHKERRQ(ierr); 18 if (!flag || pythonexe[0]==0) { 19 ierr = PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 20 } 21 PetscFunctionReturn(0); 22 } 23 24 static PetscErrorCode PetscPythonFindLibrary(const char pythonexe[PETSC_MAX_PATH_LEN],char pythonlib[PETSC_MAX_PATH_LEN]) 25 { 26 const char cmdline[] = "-c 'from distutils import sysconfig; print(sysconfig.get_config_var('LIBPYTHON'))'"; 27 char command[PETSC_MAX_PATH_LEN+1+sizeof(cmdline)+1],*eol; 28 FILE *fp = NULL; 29 PetscBool found = PETSC_FALSE; 30 PetscErrorCode ierr; 31 32 PetscFunctionBegin; 33 #if defined(PETSC_PYTHON_LIB) 34 ierr = PetscStrcpy(pythonlib,PETSC_PYTHON_LIB);CHKERRQ(ierr); 35 PetscFunctionReturn(0); 36 #endif 37 38 /* call Python to find out the name of the Python dynamic library */ 39 ierr = PetscStrncpy(command,pythonexe,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 40 ierr = PetscStrcat(command," ");CHKERRQ(ierr); 41 ierr = PetscStrcat(command,cmdline);CHKERRQ(ierr); 42 #if defined(PETSC_HAVE_POPEN) 43 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fp);CHKERRQ(ierr); 44 if (!fgets(pythonlib,PETSC_MAX_PATH_LEN,fp)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe); 45 ierr = PetscPClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr); 46 #else 47 SETERRQ(PETSC_COMM_SELF,1,"Python: Aborted due to missing popen()"); 48 #endif 49 /* remove newlines */ 50 ierr = PetscStrchr(pythonlib,'\n',&eol);CHKERRQ(ierr); 51 if (eol) eol[0] = 0; 52 ierr = PetscTestFile(pythonlib,'r',&found);CHKERRQ(ierr); 53 ierr = PetscInfo2(0,"Python library %s found %d\n",pythonlib,found);CHKERRQ(ierr); 54 PetscFunctionReturn(0); 55 } 56 57 /* ---------------------------------------------------------------- */ 58 59 typedef struct _Py_object_t PyObject; /* fake definition */ 60 61 static PyObject* Py_None = 0; 62 63 static const char* (*Py_GetVersion)(void); 64 65 static int (*Py_IsInitialized)(void); 66 static void (*Py_InitializeEx)(int); 67 static void (*Py_Finalize)(void); 68 69 static void (*PySys_SetArgv)(int,char**); 70 static PyObject* (*PySys_GetObject)(const char*); 71 static PyObject* (*PyObject_CallMethod)(PyObject*,const char*, const char*, ...); 72 static PyObject* (*PyImport_ImportModule)(const char*); 73 74 static void (*Py_IncRef)(PyObject*); 75 static void (*Py_DecRef)(PyObject*); 76 77 static void (*PyErr_Clear)(void); 78 static PyObject* (*PyErr_Occurred)(void); 79 static void (*PyErr_Fetch)(PyObject**,PyObject**,PyObject**); 80 static void (*PyErr_NormalizeException)(PyObject**,PyObject**, PyObject**); 81 static void (*PyErr_Display)(PyObject*,PyObject*,PyObject*); 82 static void (*PyErr_Restore)(PyObject*,PyObject*,PyObject*); 83 84 85 #define PetscDLPyLibOpen(libname) \ 86 PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname) 87 #define PetscDLPyLibSym(symbol, value) \ 88 PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,symbol,(void**)value) 89 #define PetscDLPyLibClose(comm) \ 90 do { } while (0) 91 92 static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[]) 93 { 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 /* open the Python dynamic library */ 98 ierr = PetscDLPyLibOpen(pythonlib);CHKERRQ(ierr); 99 ierr = PetscInfo1(0,"Python: loaded dynamic library %s\n", pythonlib);CHKERRQ(ierr); 100 /* look required symbols from the Python C-API */ 101 ierr = PetscDLPyLibSym("_Py_NoneStruct" , &Py_None );CHKERRQ(ierr); 102 ierr = PetscDLPyLibSym("Py_GetVersion" , &Py_GetVersion );CHKERRQ(ierr); 103 ierr = PetscDLPyLibSym("Py_IsInitialized" , &Py_IsInitialized );CHKERRQ(ierr); 104 ierr = PetscDLPyLibSym("Py_InitializeEx" , &Py_InitializeEx );CHKERRQ(ierr); 105 ierr = PetscDLPyLibSym("Py_Finalize" , &Py_Finalize );CHKERRQ(ierr); 106 ierr = PetscDLPyLibSym("PySys_GetObject" , &PySys_GetObject );CHKERRQ(ierr); 107 ierr = PetscDLPyLibSym("PySys_SetArgv" , &PySys_SetArgv );CHKERRQ(ierr); 108 ierr = PetscDLPyLibSym("PyObject_CallMethod" , &PyObject_CallMethod );CHKERRQ(ierr); 109 ierr = PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule );CHKERRQ(ierr); 110 ierr = PetscDLPyLibSym("Py_IncRef" , &Py_IncRef );CHKERRQ(ierr); 111 ierr = PetscDLPyLibSym("Py_DecRef" , &Py_DecRef );CHKERRQ(ierr); 112 ierr = PetscDLPyLibSym("PyErr_Clear" , &PyErr_Clear );CHKERRQ(ierr); 113 ierr = PetscDLPyLibSym("PyErr_Occurred" , &PyErr_Occurred );CHKERRQ(ierr); 114 ierr = PetscDLPyLibSym("PyErr_Fetch" , &PyErr_Fetch );CHKERRQ(ierr); 115 ierr = PetscDLPyLibSym("PyErr_NormalizeException", &PyErr_NormalizeException);CHKERRQ(ierr); 116 ierr = PetscDLPyLibSym("PyErr_Display", &PyErr_Display );CHKERRQ(ierr); 117 ierr = PetscDLPyLibSym("PyErr_Restore", &PyErr_Restore );CHKERRQ(ierr); 118 /* XXX TODO: check that ALL symbols were there !!! */ 119 if (!Py_None) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library"); 120 if (!Py_GetVersion) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library"); 121 if (!Py_IsInitialized) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library"); 122 if (!Py_InitializeEx) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library"); 123 if (!Py_Finalize) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library"); 124 ierr = PetscInfo(0,"Python: all required symbols loaded from Python dynamic library\n");CHKERRQ(ierr); 125 PetscFunctionReturn(0); 126 } 127 128 /* ---------------------------------------------------------------- */ 129 130 static char PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 }; 131 static char PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 }; 132 static PetscBool PetscBeganPython = PETSC_FALSE; 133 134 /*@C 135 PetscPythonFinalize - Finalize Python. 136 137 Level: intermediate 138 139 .keywords: Python 140 @*/ 141 PetscErrorCode PetscPythonFinalize(void) 142 { 143 PetscFunctionBegin; 144 if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); } 145 PetscBeganPython = PETSC_FALSE; 146 PetscFunctionReturn(0); 147 } 148 149 /*@C 150 PetscPythonInitialize - Initialize Python and import petsc4py. 151 152 Input Parameter: 153 + pyexe - path to the Python interpreter executable, or NULL. 154 - pylib - full path to the Python dynamic library, or NULL. 155 156 Level: intermediate 157 158 .keywords: Python 159 160 @*/ 161 PetscErrorCode PetscPythonInitialize(const char pyexe[],const char pylib[]) 162 { 163 PyObject *module = 0; 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 if (PetscBeganPython) PetscFunctionReturn(0); 168 /* Python executable */ 169 if (pyexe && pyexe[0] != 0) { 170 ierr = PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe));CHKERRQ(ierr); 171 } else { 172 ierr = PetscPythonFindExecutable(PetscPythonExe);CHKERRQ(ierr); 173 } 174 /* Python dynamic library */ 175 if (pylib && pylib[0] != 0) { 176 ierr = PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib));CHKERRQ(ierr); 177 } else { 178 ierr = PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib);CHKERRQ(ierr); 179 } 180 /* dynamically load Python library */ 181 ierr = PetscPythonLoadLibrary(PetscPythonLib);CHKERRQ(ierr); 182 /* initialize Python */ 183 PetscBeganPython = PETSC_FALSE; 184 if (!Py_IsInitialized()) { 185 static PetscBool registered = PETSC_FALSE; 186 const char *py_version; 187 PyObject *sys_path; 188 char path[PETSC_MAX_PATH_LEN] = { 0 }; 189 190 /* initialize Python */ 191 Py_InitializeEx(0); /* 0: do not install signal handlers */ 192 /* build 'sys.argv' list */ 193 py_version = Py_GetVersion(); 194 if (py_version[0] == '2') { 195 int argc = 0; char **argv = 0; 196 ierr = PetscGetArgs(&argc,&argv);CHKERRQ(ierr); 197 PySys_SetArgv(argc,argv); 198 } 199 if (py_version[0] == '3') { 200 /* XXX 'argv' is type 'wchar_t**' */ 201 PySys_SetArgv(0,NULL); 202 } 203 /* add PETSC_LIB_DIR in front of 'sys.path' */ 204 sys_path = PySys_GetObject("path"); 205 if (sys_path) { 206 ierr = PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path));CHKERRQ(ierr); 207 Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path)); 208 } 209 /* register finalizer */ 210 if (!registered) { 211 ierr = PetscRegisterFinalize(PetscPythonFinalize);CHKERRQ(ierr); 212 213 registered = PETSC_TRUE; 214 } 215 PetscBeganPython = PETSC_TRUE; 216 } 217 /* import 'petsc4py.PETSc' module */ 218 module = PyImport_ImportModule("petsc4py.PETSc"); 219 if (module) { 220 ierr = PetscInfo(0,"Python: successfully imported module 'petsc4py.PETSc'\n");CHKERRQ(ierr); 221 222 Py_DecRef(module); module = 0; 223 } else { 224 PetscPythonPrintError(); 225 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: could not import module 'petsc4py.PETSc', perhaps your PYTHONPATH does not contain it\n"); 226 } 227 PetscFunctionReturn(0); 228 } 229 230 /*@C 231 PetscPythonPrintError - Print Python errors. 232 233 Level: developer 234 235 .keywords: Python 236 237 @*/ 238 PetscErrorCode PetscPythonPrintError(void) 239 { 240 PyObject *exc=0, *val=0, *tb=0; 241 242 PetscFunctionBegin; 243 if (!PetscBeganPython) PetscFunctionReturn(0); 244 if (!PyErr_Occurred()) PetscFunctionReturn(0); 245 PyErr_Fetch(&exc,&val,&tb); 246 PyErr_NormalizeException(&exc,&val,&tb); 247 PyErr_Display(exc ? exc : Py_None, 248 val ? val : Py_None, 249 tb ? tb : Py_None); 250 PyErr_Restore(exc,val,tb); 251 PetscFunctionReturn(0); 252 } 253 254 /* ---------------------------------------------------------------- */ 255 256 PETSC_EXTERN PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]); 257 PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]) = NULL; 258 259 /*@C 260 PetscPythonMonitorSet - Set Python monitor 261 262 Level: developer 263 264 .keywords: Python 265 266 @*/ 267 PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[]) 268 { 269 PetscErrorCode ierr; 270 271 PetscFunctionBegin; 272 PetscValidHeader(obj,1); 273 PetscValidCharPointer(url,2); 274 if (!PetscPythonMonitorSet_C) { 275 ierr = PetscPythonInitialize(NULL,NULL);CHKERRQ(ierr); 276 if (!PetscPythonMonitorSet_C) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Couldn't initialize Python support for monitors"); 277 } 278 ierr = PetscPythonMonitorSet_C(obj,url);CHKERRQ(ierr); 279 PetscFunctionReturn(0); 280 } 281 282 /* ---------------------------------------------------------------- */ 283