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