Actual source code: pythonsys.c
petsc-3.10.5 2019-03-28
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 'import os;from distutils import sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),sysconfig.get_config_var(\"LDLIBRARY\")))'";
     57:   const char     cmdline2[] = "-c 'import os;from distutils import sysconfig; import sys;print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),\"libpython\"+sys.version[:3]+\".dylib\"))'";
     58:   const char     cmdline3[] = "-c 'import os;from distutils import sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBPL\"),sysconfig.get_config_var(\"LDLIBRARY\")))'";
     59:   const char     cmdline4[] = "-c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBPYTHON\"))'";

     61:   PetscBool      found = PETSC_FALSE;

     65: #if defined(PETSC_PYTHON_LIB)
     66:   PetscStrcpy(pythonlib,PETSC_PYTHON_LIB);
     67:   return(0);
     68: #endif

     70:   PetscPythonFindLibraryName(pythonexe,cmdline1,pythonlib,&found);
     71:   if (!found) {
     72:     PetscPythonFindLibraryName(pythonexe,cmdline2,pythonlib,&found);
     73:   }
     74:   if (!found) {
     75:     PetscPythonFindLibraryName(pythonexe,cmdline3,pythonlib,&found);
     76:   }
     77:   if (!found) {
     78:     PetscPythonFindLibraryName(pythonexe,cmdline4,pythonlib,&found);
     79:   }
     80:   PetscInfo2(0,"Python library  %s found %d\n",pythonlib,found);
     81:   return(0);
     82: }

     84: /* ---------------------------------------------------------------- */

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

     88: static PyObject* Py_None = 0;

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

     92: static int       (*Py_IsInitialized)(void);
     93: static void      (*Py_InitializeEx)(int);
     94: static void      (*Py_Finalize)(void);

     96: static void      (*PySys_SetArgv)(int,void*);
     97: static PyObject* (*PySys_GetObject)(const char*);
     98: static PyObject* (*PyObject_CallMethod)(PyObject*,const char*, const char*, ...);
     99: static PyObject* (*PyImport_ImportModule)(const char*);

    101: static void      (*Py_IncRef)(PyObject*);
    102: static void      (*Py_DecRef)(PyObject*);

    104: static void      (*PyErr_Clear)(void);
    105: static PyObject* (*PyErr_Occurred)(void);
    106: static void      (*PyErr_Fetch)(PyObject**,PyObject**,PyObject**);
    107: static void      (*PyErr_NormalizeException)(PyObject**,PyObject**, PyObject**);
    108: static void      (*PyErr_Display)(PyObject*,PyObject*,PyObject*);
    109: static void      (*PyErr_Restore)(PyObject*,PyObject*,PyObject*);

    112: #define PetscDLPyLibOpen(libname) \
    113:   PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname)
    114: #define PetscDLPyLibSym(symbol, value) \
    115:   PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,symbol,(void**)value)
    116: #define PetscDLPyLibClose(comm) \
    117:   do { } while (0)

    119: static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[])
    120: {

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

    155: /* ---------------------------------------------------------------- */

    157: static char      PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 };
    158: static char      PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 };
    159: static PetscBool PetscBeganPython = PETSC_FALSE;

    161: /*@C
    162:   PetscPythonFinalize - Finalize Python.

    164:   Level: intermediate

    166: .keywords: Python
    167: @*/
    168: PetscErrorCode  PetscPythonFinalize(void)
    169: {
    171:   if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); }
    172:   PetscBeganPython = PETSC_FALSE;
    173:   return(0);
    174: }

    176: /*@C
    177:   PetscPythonInitialize - Initialize Python and import petsc4py.

    179:    Input Parameter:
    180: +  pyexe - path to the Python interpreter executable, or NULL.
    181: -  pylib - full path to the Python dynamic library, or NULL.

    183:   Level: intermediate

    185: .keywords: Python

    187: @*/
    188: PetscErrorCode  PetscPythonInitialize(const char pyexe[],const char pylib[])
    189: {
    190:   PyObject       *module = 0;

    194:   if (PetscBeganPython) return(0);
    195:   /* Python executable */
    196:   if (pyexe && pyexe[0] != 0) {
    197:     PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe));
    198:   } else {
    199:     PetscPythonFindExecutable(PetscPythonExe);
    200:   }
    201:   /* Python dynamic library */
    202:   if (pylib && pylib[0] != 0) {
    203:     PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib));
    204:   } else {
    205:     PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib);
    206:   }
    207:   /* dynamically load Python library */
    208:   PetscPythonLoadLibrary(PetscPythonLib);
    209:   /* initialize Python */
    210:   PetscBeganPython = PETSC_FALSE;
    211:   if (!Py_IsInitialized()) {
    212:     static PetscBool registered = PETSC_FALSE;
    213:     const char       *py_version;
    214:     PyObject         *sys_path;
    215:     char             path[PETSC_MAX_PATH_LEN] = { 0 };

    217:     /* initialize Python */
    218:     Py_InitializeEx(0); /* 0: do not install signal handlers */
    219:     /*  build 'sys.argv' list */
    220:     py_version = Py_GetVersion();
    221:     if (py_version[0] == '2') {
    222:       int argc = 0; char *argv[1] = {NULL};
    223:       PySys_SetArgv(argc,argv);
    224:     }
    225:     if (py_version[0] == '3') {
    226:       int argc = 0; wchar_t *argv[1] = {NULL};
    227:       PySys_SetArgv(argc,argv);
    228:     }
    229:     /* add PETSC_LIB_DIR in front of 'sys.path' */
    230:     sys_path = PySys_GetObject("path");
    231:     if (sys_path) {
    232:       PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path));
    233:       Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path));
    234:     }
    235:     /* register finalizer */
    236:     if (!registered) {
    237:       PetscRegisterFinalize(PetscPythonFinalize);
    238:       registered = PETSC_TRUE;
    239:     }
    240:     PetscBeganPython = PETSC_TRUE;
    241:   }
    242:   /* import 'petsc4py.PETSc' module */
    243:   module = PyImport_ImportModule("petsc4py.PETSc");
    244:   if (module) {
    245:     PetscInfo(0,"Python: successfully imported  module 'petsc4py.PETSc'\n");

    247:     Py_DecRef(module); module = 0;
    248:   } else {
    249:     PetscPythonPrintError();
    250:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: could not import module 'petsc4py.PETSc', perhaps your PYTHONPATH does not contain it\n");
    251:   }
    252:   return(0);
    253: }

    255: /*@C
    256:   PetscPythonPrintError - Print Python errors.

    258:   Level: developer

    260: .keywords: Python

    262: @*/
    263: PetscErrorCode  PetscPythonPrintError(void)
    264: {
    265:   PyObject *exc=0, *val=0, *tb=0;

    268:   if (!PetscBeganPython) return(0);
    269:   if (!PyErr_Occurred()) return(0);
    270:   PyErr_Fetch(&exc,&val,&tb);
    271:   PyErr_NormalizeException(&exc,&val,&tb);
    272:   PyErr_Display(exc ? exc : Py_None,
    273:                 val ? val : Py_None,
    274:                 tb  ? tb  : Py_None);
    275:   PyErr_Restore(exc,val,tb);
    276:   return(0);
    277: }

    279: /* ---------------------------------------------------------------- */

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

    284: /*@C
    285:   PetscPythonMonitorSet - Set Python monitor

    287:   Level: developer

    289: .keywords: Python

    291: @*/
    292: PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[])
    293: {

    299:   if (!PetscPythonMonitorSet_C) {
    300:     PetscPythonInitialize(NULL,NULL);
    301:     if (!PetscPythonMonitorSet_C) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Couldn't initialize Python support for monitors");
    302:   }
    303:   PetscPythonMonitorSet_C(obj,url);
    304:   return(0);
    305: }

    307: /* ---------------------------------------------------------------- */