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