Actual source code: pythonsys.c

petsc-3.9.1 2018-04-29
Report Typos and Errors
  1:  #include <petsc/private/petscimpl.h>

  3: /* ---------------------------------------------------------------- */

  5: #if !defined(PETSC_PYTHON_EXE)
  6: #define PETSC_PYTHON_EXE "python"
  7: #endif

  9: static PetscErrorCode PetscPythonFindExecutable(char pythonexe[PETSC_MAX_PATH_LEN])
 10: {
 11:   PetscBool      flag;

 15:   /* get the path for the Python interpreter executable */
 16:   PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);
 17:   PetscOptionsGetString(NULL,NULL,"-python",pythonexe,PETSC_MAX_PATH_LEN,&flag);
 18:   if (!flag || pythonexe[0]==0) {
 19:     PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);
 20:   }
 21:   return(0);
 22: }

 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;

 35:   /* call Python to find out the name of the Python dynamic library */
 36:   PetscStrncpy(command,pythonexe,PETSC_MAX_PATH_LEN);
 37:   PetscStrcat(command," ");
 38:   PetscStrcat(command,attempt);
 39: #if defined(PETSC_HAVE_POPEN)
 40:   PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fp);
 41:   if (!fgets(pythonlib,PETSC_MAX_PATH_LEN,fp)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe);
 42:   PetscPClose(PETSC_COMM_SELF,fp);
 43: #else
 44:   SETERRQ(PETSC_COMM_SELF,1,"Python: Aborted due to missing popen()");
 45: #endif
 46:   /* remove newlines */
 47:   PetscStrchr(pythonlib,'\n',&eol);
 48:   if (eol) eol[0] = 0;
 49:   PetscTestFile(pythonlib,'r',found);
 50:   return(0);
 51: }


 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:   PetscBool      found = PETSC_FALSE;

 62: #if defined(PETSC_PYTHON_LIB)
 63:   PetscStrcpy(pythonlib,PETSC_PYTHON_LIB);
 64:   return(0);
 65: #endif

 67:   PetscPythonFindLibraryName(pythonexe,cmdline1,pythonlib,&found);
 68:   if (!found) {
 69:     PetscPythonFindLibraryName(pythonexe,cmdline2,pythonlib,&found);
 70:   }
 71:   PetscInfo2(0,"Python library  %s found %d\n",pythonlib,found);
 72:   return(0);
 73: }

 75: /* ---------------------------------------------------------------- */

 77: typedef struct _Py_object_t PyObject; /* fake definition */

 79: static PyObject* Py_None = 0;

 81: static const char* (*Py_GetVersion)(void);

 83: static int       (*Py_IsInitialized)(void);
 84: static void      (*Py_InitializeEx)(int);
 85: static void      (*Py_Finalize)(void);

 87: static void      (*PySys_SetArgv)(int,char**);
 88: static PyObject* (*PySys_GetObject)(const char*);
 89: static PyObject* (*PyObject_CallMethod)(PyObject*,const char*, const char*, ...);
 90: static PyObject* (*PyImport_ImportModule)(const char*);

 92: static void      (*Py_IncRef)(PyObject*);
 93: static void      (*Py_DecRef)(PyObject*);

 95: static void      (*PyErr_Clear)(void);
 96: static PyObject* (*PyErr_Occurred)(void);
 97: static void      (*PyErr_Fetch)(PyObject**,PyObject**,PyObject**);
 98: static void      (*PyErr_NormalizeException)(PyObject**,PyObject**, PyObject**);
 99: static void      (*PyErr_Display)(PyObject*,PyObject*,PyObject*);
100: static void      (*PyErr_Restore)(PyObject*,PyObject*,PyObject*);


103: #define PetscDLPyLibOpen(libname) \
104:   PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname)
105: #define PetscDLPyLibSym(symbol, value) \
106:   PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,symbol,(void**)value)
107: #define PetscDLPyLibClose(comm) \
108:   do { } while (0)

110: static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[])
111: {

115:   /* open the Python dynamic library */
116:   PetscDLPyLibOpen(pythonlib);
117:   PetscInfo1(0,"Python: loaded dynamic library %s\n", pythonlib);
118:   /* look required symbols from the Python C-API */
119:   PetscDLPyLibSym("_Py_NoneStruct"        , &Py_None               );
120:   PetscDLPyLibSym("Py_GetVersion"         , &Py_GetVersion         );
121:   PetscDLPyLibSym("Py_IsInitialized"      , &Py_IsInitialized      );
122:   PetscDLPyLibSym("Py_InitializeEx"       , &Py_InitializeEx       );
123:   PetscDLPyLibSym("Py_Finalize"           , &Py_Finalize           );
124:   PetscDLPyLibSym("PySys_GetObject"       , &PySys_GetObject       );
125:   PetscDLPyLibSym("PySys_SetArgv"         , &PySys_SetArgv         );
126:   PetscDLPyLibSym("PyObject_CallMethod"   , &PyObject_CallMethod   );
127:   PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule );
128:   PetscDLPyLibSym("Py_IncRef"             , &Py_IncRef             );
129:   PetscDLPyLibSym("Py_DecRef"             , &Py_DecRef             );
130:   PetscDLPyLibSym("PyErr_Clear"           , &PyErr_Clear           );
131:   PetscDLPyLibSym("PyErr_Occurred"        , &PyErr_Occurred        );
132:   PetscDLPyLibSym("PyErr_Fetch"             , &PyErr_Fetch             );
133:   PetscDLPyLibSym("PyErr_NormalizeException", &PyErr_NormalizeException);
134:   PetscDLPyLibSym("PyErr_Display",            &PyErr_Display           );
135:   PetscDLPyLibSym("PyErr_Restore",            &PyErr_Restore           );
136:   /* XXX TODO: check that ALL symbols were there !!! */
137:   if (!Py_None)          SETERRQ1(PETSC_COMM_SELF,1,"Python: failed to load symbols from Python dynamic library %s",pythonlib);
138:   if (!Py_GetVersion)    SETERRQ1(PETSC_COMM_SELF,1,"Python: failed to load symbols from Python dynamic library %s",pythonlib);
139:   if (!Py_IsInitialized) SETERRQ1(PETSC_COMM_SELF,1,"Python: failed to load symbols from Python dynamic library %s",pythonlib);
140:   if (!Py_InitializeEx)  SETERRQ1(PETSC_COMM_SELF,1,"Python: failed to load symbols from Python dynamic library %s",pythonlib);
141:   if (!Py_Finalize)      SETERRQ1(PETSC_COMM_SELF,1,"Python: failed to load symbols from Python dynamic library %s",pythonlib);
142:   PetscInfo1(0,"Python: all required symbols loaded from Python dynamic library %s\n",pythonlib);
143:   return(0);
144: }

146: /* ---------------------------------------------------------------- */

148: static char      PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 };
149: static char      PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 };
150: static PetscBool PetscBeganPython = PETSC_FALSE;

152: /*@C
153:   PetscPythonFinalize - Finalize Python.

155:   Level: intermediate

157: .keywords: Python
158: @*/
159: PetscErrorCode  PetscPythonFinalize(void)
160: {
162:   if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); }
163:   PetscBeganPython = PETSC_FALSE;
164:   return(0);
165: }

167: /*@C
168:   PetscPythonInitialize - Initialize Python and import petsc4py.

170:    Input Parameter:
171: +  pyexe - path to the Python interpreter executable, or NULL.
172: -  pylib - full path to the Python dynamic library, or NULL.

174:   Level: intermediate

176: .keywords: Python

178: @*/
179: PetscErrorCode  PetscPythonInitialize(const char pyexe[],const char pylib[])
180: {
181:   PyObject       *module = 0;

185:   if (PetscBeganPython) return(0);
186:   /* Python executable */
187:   if (pyexe && pyexe[0] != 0) {
188:     PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe));
189:   } else {
190:     PetscPythonFindExecutable(PetscPythonExe);
191:   }
192:   /* Python dynamic library */
193:   if (pylib && pylib[0] != 0) {
194:     PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib));
195:   } else {
196:     PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib);
197:   }
198:   /* dynamically load Python library */
199:   PetscPythonLoadLibrary(PetscPythonLib);
200:   /* initialize Python */
201:   PetscBeganPython = PETSC_FALSE;
202:   if (!Py_IsInitialized()) {
203:     static PetscBool registered = PETSC_FALSE;
204:     const char       *py_version;
205:     PyObject         *sys_path;
206:     char             path[PETSC_MAX_PATH_LEN] = { 0 };

208:     /* initialize Python */
209:     Py_InitializeEx(0); /* 0: do not install signal handlers */
210:     /*  build 'sys.argv' list */
211:     py_version = Py_GetVersion();
212:     if (py_version[0] == '2') {
213:       int argc = 0; char **argv = 0;
214:       PetscGetArgs(&argc,&argv);
215:       PySys_SetArgv(argc,argv);
216:     }
217:     if (py_version[0] == '3') {
218:       /* XXX 'argv' is type 'wchar_t**' */
219:       PySys_SetArgv(0,NULL);
220:     }
221:     /* add PETSC_LIB_DIR in front of 'sys.path' */
222:     sys_path = PySys_GetObject("path");
223:     if (sys_path) {
224:       PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path));
225:       Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path));
226:     }
227:     /* register finalizer */
228:     if (!registered) {
229:       PetscRegisterFinalize(PetscPythonFinalize);

231:       registered = PETSC_TRUE;
232:     }
233:     PetscBeganPython = PETSC_TRUE;
234:   }
235:   /* import 'petsc4py.PETSc' module */
236:   module = PyImport_ImportModule("petsc4py.PETSc");
237:   if (module) {
238:     PetscInfo(0,"Python: successfully imported  module 'petsc4py.PETSc'\n");

240:     Py_DecRef(module); module = 0;
241:   } else {
242:     PetscPythonPrintError();
243:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: could not import module 'petsc4py.PETSc', perhaps your PYTHONPATH does not contain it\n");
244:   }
245:   return(0);
246: }

248: /*@C
249:   PetscPythonPrintError - Print Python errors.

251:   Level: developer

253: .keywords: Python

255: @*/
256: PetscErrorCode  PetscPythonPrintError(void)
257: {
258:   PyObject *exc=0, *val=0, *tb=0;

261:   if (!PetscBeganPython) return(0);
262:   if (!PyErr_Occurred()) return(0);
263:   PyErr_Fetch(&exc,&val,&tb);
264:   PyErr_NormalizeException(&exc,&val,&tb);
265:   PyErr_Display(exc ? exc : Py_None,
266:                 val ? val : Py_None,
267:                 tb  ? tb  : Py_None);
268:   PyErr_Restore(exc,val,tb);
269:   return(0);
270: }

272: /* ---------------------------------------------------------------- */

274: PETSC_EXTERN PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]);
275: PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]) = NULL;

277: /*@C
278:   PetscPythonMonitorSet - Set Python monitor

280:   Level: developer

282: .keywords: Python

284: @*/
285: PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[])
286: {

292:   if (!PetscPythonMonitorSet_C) {
293:     PetscPythonInitialize(NULL,NULL);
294:     if (!PetscPythonMonitorSet_C) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Couldn't initialize Python support for monitors");
295:   }
296:   PetscPythonMonitorSet_C(obj,url);
297:   return(0);
298: }

300: /* ---------------------------------------------------------------- */