Actual source code: pythonsys.c

petsc-3.3-p7 2013-05-11
  1: #include <petscsys.h>       /*I "petscsys.h" I*/

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

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

 11: static PetscErrorCode PetscPythonFindExecutable(char pythonexe[PETSC_MAX_PATH_LEN])
 12: {
 13:   PetscBool      flag;
 16:   /* get the path for the Python interpreter executable */
 17:   PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);
 18:   PetscOptionsGetString(PETSC_NULL,"-python",pythonexe,PETSC_MAX_PATH_LEN,&flag);
 19:   if (!flag || pythonexe[0]==0) {
 20:     PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);
 21:   }
 22:   return(0);
 23: }

 27: static PetscErrorCode PetscPythonFindLibrary(char pythonexe[PETSC_MAX_PATH_LEN],
 28:                                              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;

 39: #if defined(PETSC_PYTHON_LIB)
 40:   PetscStrcpy(pythonlib,PETSC_PYTHON_LIB);
 41:   return(0);
 42: #endif

 44:   /* call Python to find out the name of the Python dynamic library */
 45:   PetscStrncpy(command,pythonexe,PETSC_MAX_PATH_LEN);
 46:   PetscStrcat(command," ");
 47:   PetscStrcat(command,cmdline);
 48: #if defined(PETSC_HAVE_POPEN)
 49:   PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,command,"r",&fp);
 50:   if (!fgets(prefix,sizeof(prefix),fp))
 51:     { SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe); }
 52:   if (!fgets(version,sizeof(version),fp))
 53:     { SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe); }
 54:   PetscPClose(PETSC_COMM_SELF,fp);
 55: #else
 56:   SETERRQ(PETSC_COMM_SELF,1,"Python: Aborted due to missing popen()");
 57: #endif
 58:   /* remove newlines */
 59:   PetscStrchr(prefix,'\n',&eol);
 60:   if (eol) eol[0] = 0;
 61:   PetscStrchr(version,'\n',&eol);
 62:   if (eol) eol[0] = 0;

 64:   /* test for $prefix/lib64/libpythonX.X[.so]*/
 65:   PetscStrcpy(pythonlib,prefix);
 66:   PetscStrcat(pythonlib,sep);
 67:   PetscStrcat(pythonlib,"lib64");
 68:   PetscTestDirectory(pythonlib,'r',&found);
 69:   if (found) {
 70:     PetscStrcat(pythonlib,sep);
 71:     PetscStrcat(pythonlib,"libpython");
 72:     PetscStrcat(pythonlib,version);
 73:     PetscDLLibraryRetrieve(PETSC_COMM_SELF,pythonlib,path,PETSC_MAX_PATH_LEN,&found);
 74:     if (found) return(0);
 75:   }

 77:   /* test for $prefix/lib/libpythonX.X[.so]*/
 78:   PetscStrcpy(pythonlib,prefix);
 79:   PetscStrcat(pythonlib,sep);
 80:   PetscStrcat(pythonlib,"lib");
 81:   PetscTestDirectory(pythonlib,'r',&found);
 82:   if (found) {
 83:     PetscStrcat(pythonlib,sep);
 84:     PetscStrcat(pythonlib,"libpython");
 85:     PetscStrcat(pythonlib,version);
 86:     PetscDLLibraryRetrieve(PETSC_COMM_SELF,pythonlib,path,PETSC_MAX_PATH_LEN,&found);
 87:     if (found) return(0);
 88:   }

 90:   /* nothing good found */
 91:   PetscMemzero(pythonlib,PETSC_MAX_PATH_LEN);
 92:   PetscInfo(0,"Python dynamic library not found\n");

 94:   return(0);
 95: }

 97: /* ---------------------------------------------------------------- */

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

101: static PyObject* Py_None = 0;

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

105: static int       (*Py_IsInitialized)(void);
106: static void      (*Py_InitializeEx)(int);
107: static void      (*Py_Finalize)(void);

109: static void      (*PySys_SetArgv)(int, char **);
110: static PyObject* (*PySys_GetObject)(const char *);
111: static PyObject* (*PyObject_CallMethod)(PyObject *, const char *, const char *, ...);
112: static PyObject* (*PyImport_ImportModule)(const char *);

114: static void      (*Py_IncRef)(PyObject *);
115: static void      (*Py_DecRef)(PyObject *);

117: static void      (*PyErr_Clear)(void);
118: static PyObject* (*PyErr_Occurred)(void);
119: static void      (*PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
120: static void      (*PyErr_NormalizeException)(PyObject **, PyObject **, PyObject **);
121: static void      (*PyErr_Display)(PyObject *, PyObject *, PyObject *);
122: static void      (*PyErr_Restore)(PyObject *, PyObject *, PyObject *);


125: #define PetscDLPyLibOpen(libname) \
126:   PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname)
127: #define PetscDLPyLibSym(symbol, value) \
128:   PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,PETSC_NULL,symbol,(void**)value)
129: #define PetscDLPyLibClose(comm) \
130:   do { } while(0)

134: static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[])
135: {

139:   /* open the Python dynamic library */
140:   PetscDLPyLibOpen(pythonlib);
141:   PetscInfo1(0,"Python: loaded dynamic library %s\n", pythonlib);
142:   /* look required symbols from the Python C-API */
143:   PetscDLPyLibSym("_Py_NoneStruct"        , &Py_None               );
144:   PetscDLPyLibSym("Py_GetVersion"         , &Py_GetVersion         );
145:   PetscDLPyLibSym("Py_IsInitialized"      , &Py_IsInitialized      );
146:   PetscDLPyLibSym("Py_InitializeEx"       , &Py_InitializeEx       );
147:   PetscDLPyLibSym("Py_Finalize"           , &Py_Finalize           );
148:   PetscDLPyLibSym("PySys_GetObject"       , &PySys_GetObject       );
149:   PetscDLPyLibSym("PySys_SetArgv"         , &PySys_SetArgv         );
150:   PetscDLPyLibSym("PyObject_CallMethod"   , &PyObject_CallMethod   );
151:   PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule );
152:   PetscDLPyLibSym("Py_IncRef"             , &Py_IncRef             );
153:   PetscDLPyLibSym("Py_DecRef"             , &Py_DecRef             );
154:   PetscDLPyLibSym("PyErr_Clear"           , &PyErr_Clear           );
155:   PetscDLPyLibSym("PyErr_Occurred"        , &PyErr_Occurred        );
156:   PetscDLPyLibSym("PyErr_Fetch"             , &PyErr_Fetch             );
157:   PetscDLPyLibSym("PyErr_NormalizeException", &PyErr_NormalizeException);
158:   PetscDLPyLibSym("PyErr_Display",            &PyErr_Display           );
159:   PetscDLPyLibSym("PyErr_Restore",            &PyErr_Restore           );
160:   /* XXX TODO: check that ALL symbols were there !!! */
161:   if (!Py_None)          SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library");
162:   if (!Py_GetVersion)    SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library");
163:   if (!Py_IsInitialized) SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library");
164:   if (!Py_InitializeEx)  SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library");
165:   if (!Py_Finalize)      SETERRQ(PETSC_COMM_SELF,1,"Python: failed to load symbols from dynamic library");
166:   PetscInfo(0,"Python: all required symbols loaded from Python dynamic library\n");

168:   return(0);
169: }

171: /* ---------------------------------------------------------------- */

173: static char       PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 };
174: static char       PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 };
175: static PetscBool  PetscBeganPython = PETSC_FALSE;

179: /*@C
180:   PetscPythonFinalize - Finalize Python.

182:   Level: intermediate

184: .keywords: Python
185: @*/
186: PetscErrorCode  PetscPythonFinalize(void)
187: {
189:   if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); }
190:   PetscBeganPython = PETSC_FALSE;
191:   return(0);
192: }

196: /*@C
197:   PetscPythonInitialize - Initialize Python and import petsc4py.

199:    Input Parameter:
200: +  pyexe - path to the Python interpreter executable, or PETSC_NULL.
201: -  pylib - full path to the Python dynamic library, or PETSC_NULL.

203:   Level: intermediate

205: .keywords: Python

207: @*/
208: PetscErrorCode  PetscPythonInitialize(const char pyexe[],const char pylib[])
209: {
210:   PyObject          *module    = 0;
211:   PetscErrorCode    ierr;
213:   if (PetscBeganPython) return(0);
214:   /* Python executable */
215:   if (pyexe && pyexe[0] != 0) {
216:     PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe));
217:   } else {
218:     PetscPythonFindExecutable(PetscPythonExe);
219:   }
220:   /* Python dynamic library */
221:   if (pylib && pylib[0] != 0) {
222:     PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib));
223:   } else {
224:     PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib);
225:   }
226:   /* dynamically load Python library */
227:   PetscPythonLoadLibrary(PetscPythonLib);
228:   /* initialize Python */
229:   PetscBeganPython = PETSC_FALSE;
230:   if (!Py_IsInitialized()) {
231:     static PetscBool registered = PETSC_FALSE;
232:     const char *py_version;
233:     PyObject *sys_path;
234:     char path[PETSC_MAX_PATH_LEN] = { 0 };
235:     /* initialize Python */
236:     Py_InitializeEx(0); /* 0: do not install signal handlers */
237:     /*  build 'sys.argv' list */
238:     py_version = Py_GetVersion();
239:     if (py_version[0] == '2') {
240:       int argc = 0; char **argv = 0;
241:       PetscGetArgs(&argc,&argv);
242:       PySys_SetArgv(argc,argv);
243:     }
244:     if (py_version[0] == '3') {
245:       /* XXX 'argv' is type 'wchar_t**' */
246:       PySys_SetArgv(0,PETSC_NULL);
247:     }
248:     /* add PETSC_LIB_DIR in front of 'sys.path' */
249:     sys_path = PySys_GetObject("path");
250:     if (sys_path) {
251:       PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path));
252:       Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path));
253:     }
254:     /* register finalizer */
255:     if (!registered) {
256:       PetscRegisterFinalize(PetscPythonFinalize);
257:       registered = PETSC_TRUE;
258:     }
259:     PetscBeganPython = PETSC_TRUE;
260:   }
261:   /* import 'petsc4py.PETSc' module */
262:   module = PyImport_ImportModule("petsc4py.PETSc");
263:   if (module) {
264:     PetscInfo(0,"Python: successfully imported  module 'petsc4py.PETSc'\n");
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:   return(0);
271: }

275: /*@C
276:   PetscPythonPrintError - Print Python errors.

278:   Level: developer

280: .keywords: Python

282: @*/
283: PetscErrorCode  PetscPythonPrintError(void)
284: {
285:   PyObject *exc=0, *val=0, *tb=0;
287:   if (!PetscBeganPython) return(0);
288:   if (!PyErr_Occurred()) return(0);
289:   PyErr_Fetch(&exc,&val,&tb);
290:   PyErr_NormalizeException(&exc,&val,&tb);
291:   PyErr_Display(exc ? exc : Py_None,
292:                 val ? val : Py_None,
293:                 tb  ? tb  : Py_None);
294:   PyErr_Restore(exc,val,tb);
295:   return(0);
296: }

298: /* ---------------------------------------------------------------- */

300: EXTERN_C_BEGIN
301: extern PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]);
302: PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]) = PETSC_NULL;
303: EXTERN_C_END

307: /*@C
308:   PetscPythonMonitorSet - Set Python monitor

310:   Level: developer

312: .keywords: Python

314: @*/
315: PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[])
316: {
321:   if(PetscPythonMonitorSet_C == PETSC_NULL) {
322:     PetscPythonInitialize(PETSC_NULL,PETSC_NULL);
323:     if(PetscPythonMonitorSet_C == PETSC_NULL)
324:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Couldn't initialize Python support for monitors");
325:   }
326:   PetscPythonMonitorSet_C(obj,url);
327:   return(0);
328: }

330: /* ---------------------------------------------------------------- */