Actual source code: pythonsys.c

  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[],size_t len)
 10: {
 11:   PetscBool      flag;

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

 22: /*
 23:     Python does not appear to have a universal way to indicate the location of Python dynamic library so try several possibilities
 24: */
 25: static PetscErrorCode PetscPythonFindLibraryName(const char pythonexe[],const char attempt[],char pythonlib[],size_t pl,PetscBool *found)
 26: {
 27:   char           command[2*PETSC_MAX_PATH_LEN];
 28:   FILE           *fp = NULL;
 29:   char           *eol;

 31:   /* call Python to find out the name of the Python dynamic library */
 32:   PetscStrncpy(command,pythonexe,sizeof(command));
 33:   PetscStrlcat(command," ",sizeof(command));
 34:   PetscStrlcat(command,attempt,sizeof(command));
 35: #if defined(PETSC_HAVE_POPEN)
 36:   PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fp);
 38:   PetscPClose(PETSC_COMM_SELF,fp);
 39: #else
 40:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: Aborted due to missing popen()");
 41: #endif
 42:   /* remove newlines */
 43:   PetscStrchr(pythonlib,'\n',&eol);
 44:   if (eol) eol[0] = 0;
 45:   PetscTestFile(pythonlib,'r',found);
 46:   return 0;
 47: }

 49: static PetscErrorCode PetscPythonFindLibrary(const char pythonexe[],char pythonlib[],size_t pl)
 50: {
 51:   const char     cmdline1[] = "-c 'import os, sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),sysconfig.get_config_var(\"LDLIBRARY\")))'";
 52:   const char     cmdline2[] = "-c 'import os, sysconfig; import sys;print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),\"libpython\"+sys.version[:3]+\".dylib\"))'";
 53:   const char     cmdline3[] = "-c 'import os, sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBPL\"),sysconfig.get_config_var(\"LDLIBRARY\")))'";
 54:   const char     cmdline4[] = "-c 'import sysconfig; print(sysconfig.get_config_var(\"LIBPYTHON\"))'";
 55:   const char     cmdline5[] = "-c 'import os, sysconfig; import sys;print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),\"libpython\"+sys.version[:3]+\".so\"))'";

 57:   PetscBool      found = PETSC_FALSE;

 59: #if defined(PETSC_PYTHON_LIB)
 60:   PetscStrncpy(pythonlib,PETSC_PYTHON_LIB,pl);
 61:   return 0;
 62: #endif

 64:   PetscPythonFindLibraryName(pythonexe,cmdline1,pythonlib,pl,&found);
 65:   if (!found) {
 66:     PetscPythonFindLibraryName(pythonexe,cmdline2,pythonlib,pl,&found);
 67:   }
 68:   if (!found) {
 69:     PetscPythonFindLibraryName(pythonexe,cmdline3,pythonlib,pl,&found);
 70:   }
 71:   if (!found) {
 72:     PetscPythonFindLibraryName(pythonexe,cmdline4,pythonlib,pl,&found);
 73:   }
 74:   if (!found) {
 75:     PetscPythonFindLibraryName(pythonexe,cmdline5,pythonlib,pl,&found);
 76:   }
 77:   PetscInfo(NULL,"Python library  %s found %d\n",pythonlib,found);
 78:   return 0;
 79: }

 81: /* ---------------------------------------------------------------- */

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

 85: static PyObject* Py_None = NULL;

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

 89: static int       (*Py_IsInitialized)(void);
 90: static void      (*Py_InitializeEx)(int);
 91: static void      (*Py_Finalize)(void);

 93: static void      (*PySys_SetArgv)(int,void*);
 94: static PyObject* (*PySys_GetObject)(const char*);
 95: static PyObject* (*PyObject_CallMethod)(PyObject*,const char*, const char*, ...);
 96: static PyObject* (*PyImport_ImportModule)(const char*);

 98: static void      (*Py_IncRef)(PyObject*);
 99: static void      (*Py_DecRef)(PyObject*);

101: static void      (*PyErr_Clear)(void);
102: static PyObject* (*PyErr_Occurred)(void);
103: static void      (*PyErr_Fetch)(PyObject**,PyObject**,PyObject**);
104: static void      (*PyErr_NormalizeException)(PyObject**,PyObject**, PyObject**);
105: static void      (*PyErr_Display)(PyObject*,PyObject*,PyObject*);
106: static void      (*PyErr_Restore)(PyObject*,PyObject*,PyObject*);

108: #define PetscDLPyLibOpen(libname) \
109:   PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname)
110: #define PetscDLPyLibSym(symbol, value) \
111:   PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,symbol,(void**)value)
112: #define PetscDLPyLibClose(comm) \
113:   do { } while (0)

115: static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[])
116: {
117:   /* open the Python dynamic library */
118:   PetscDLPyLibOpen(pythonlib);
119:   PetscInfo(NULL,"Python: loaded dynamic library %s\n", pythonlib);
120:   /* look required symbols from the Python C-API */
121:   PetscDLPyLibSym("_Py_NoneStruct"        , &Py_None);
122:   PetscDLPyLibSym("Py_GetVersion"         , &Py_GetVersion);
123:   PetscDLPyLibSym("Py_IsInitialized"      , &Py_IsInitialized);
124:   PetscDLPyLibSym("Py_InitializeEx"       , &Py_InitializeEx);
125:   PetscDLPyLibSym("Py_Finalize"           , &Py_Finalize);
126:   PetscDLPyLibSym("PySys_GetObject"       , &PySys_GetObject);
127:   PetscDLPyLibSym("PySys_SetArgv"         , &PySys_SetArgv);
128:   PetscDLPyLibSym("PyObject_CallMethod"   , &PyObject_CallMethod);
129:   PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule);
130:   PetscDLPyLibSym("Py_IncRef"             , &Py_IncRef);
131:   PetscDLPyLibSym("Py_DecRef"             , &Py_DecRef);
132:   PetscDLPyLibSym("PyErr_Clear"           , &PyErr_Clear);
133:   PetscDLPyLibSym("PyErr_Occurred"        , &PyErr_Occurred);
134:   PetscDLPyLibSym("PyErr_Fetch"             , &PyErr_Fetch);
135:   PetscDLPyLibSym("PyErr_NormalizeException", &PyErr_NormalizeException);
136:   PetscDLPyLibSym("PyErr_Display",            &PyErr_Display);
137:   PetscDLPyLibSym("PyErr_Restore",            &PyErr_Restore);
138:   /* XXX TODO: check that ALL symbols were there !!! */
144:   PetscInfo(NULL,"Python: all required symbols loaded from Python dynamic library %s\n",pythonlib);
145:   return 0;
146: }

148: /* ---------------------------------------------------------------- */

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

154: /*@C
155:   PetscPythonFinalize - Finalize Python.

157:   Level: intermediate

159: @*/
160: PetscErrorCode  PetscPythonFinalize(void)
161: {
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: @*/
177: PetscErrorCode  PetscPythonInitialize(const char pyexe[],const char pylib[])
178: {
179:   PyObject       *module = NULL;

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

204:     /* initialize Python */
205:     Py_InitializeEx(0); /* 0: do not install signal handlers */
206:     /*  build 'sys.argv' list */
207:     py_version = Py_GetVersion();
208:     if (py_version[0] == '2') {
209:       int argc = 0; char *argv[1] = {NULL};
210:       PySys_SetArgv(argc,argv);
211:     }
212:     if (py_version[0] == '3') {
213:       int argc = 0; wchar_t *argv[1] = {NULL};
214:       PySys_SetArgv(argc,argv);
215:     }
216:     /* add PETSC_LIB_DIR in front of 'sys.path' */
217:     sys_path = PySys_GetObject("path");
218:     if (sys_path) {
219:       PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path));
220:       Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path));
221: #if defined(PETSC_PETSC4PY_INSTALL_PATH)
222:       {
223:         char *rpath;
224:         PetscStrallocpy(PETSC_PETSC4PY_INSTALL_PATH,&rpath);
225:         Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,rpath));
226:         PetscFree(rpath);
227:       }
228: #endif
229:     }
230:     /* register finalizer */
231:     if (!registered) {
232:       PetscRegisterFinalize(PetscPythonFinalize);
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:     PetscInfo(NULL,"Python: successfully imported  module 'petsc4py.PETSc'\n");

242:     Py_DecRef(module); module = NULL;
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");
246:   }
247:   return 0;
248: }

250: /*@C
251:   PetscPythonPrintError - Print Python errors.

253:   Level: developer

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

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

269: /* ---------------------------------------------------------------- */

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

274: /*@C
275:   PetscPythonMonitorSet - Set Python monitor

277:   Level: developer

279: @*/
280: PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[])
281: {
284:   if (!PetscPythonMonitorSet_C) {
285:     PetscPythonInitialize(NULL,NULL);
287:   }
288:   PetscPythonMonitorSet_C(obj,url);
289:   return 0;
290: }

292: /* ---------------------------------------------------------------- */