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