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