#include /*I "petscsys.h" I*/ /* ---------------------------------------------------------------- */ #if !defined(PETSC_PYTHON_EXE) #define PETSC_PYTHON_EXE "python" #endif static PetscErrorCode PetscPythonFindExecutable(char pythonexe[],size_t len) { PetscBool flag; PetscFunctionBegin; /* get the path for the Python interpreter executable */ CHKERRQ(PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,len)); CHKERRQ(PetscOptionsGetString(NULL,NULL,"-python",pythonexe,len,&flag)); if (!flag || pythonexe[0]==0) { CHKERRQ(PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,len)); } PetscFunctionReturn(0); } /* Python does not appear to have a universal way to indicate the location of Python dynamic library so try several possibilities */ static PetscErrorCode PetscPythonFindLibraryName(const char pythonexe[],const char attempt[],char pythonlib[],size_t pl,PetscBool *found) { char command[2*PETSC_MAX_PATH_LEN]; FILE *fp = NULL; char *eol; PetscFunctionBegin; /* call Python to find out the name of the Python dynamic library */ CHKERRQ(PetscStrncpy(command,pythonexe,sizeof(command))); CHKERRQ(PetscStrlcat(command," ",sizeof(command))); CHKERRQ(PetscStrlcat(command,attempt,sizeof(command))); #if defined(PETSC_HAVE_POPEN) CHKERRQ(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fp)); PetscCheckFalse(!fgets(pythonlib,pl,fp),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: bad output from executable: %s\nRunning: %s",pythonexe,command); CHKERRQ(PetscPClose(PETSC_COMM_SELF,fp)); #else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: Aborted due to missing popen()"); #endif /* remove newlines */ CHKERRQ(PetscStrchr(pythonlib,'\n',&eol)); if (eol) eol[0] = 0; CHKERRQ(PetscTestFile(pythonlib,'r',found)); PetscFunctionReturn(0); } static PetscErrorCode PetscPythonFindLibrary(const char pythonexe[],char pythonlib[],size_t pl) { const char cmdline1[] = "-c 'import os, sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),sysconfig.get_config_var(\"LDLIBRARY\")))'"; const char cmdline2[] = "-c 'import os, sysconfig; import sys;print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),\"libpython\"+sys.version[:3]+\".dylib\"))'"; const char cmdline3[] = "-c 'import os, sysconfig; print(os.path.join(sysconfig.get_config_var(\"LIBPL\"),sysconfig.get_config_var(\"LDLIBRARY\")))'"; const char cmdline4[] = "-c 'import sysconfig; print(sysconfig.get_config_var(\"LIBPYTHON\"))'"; const char cmdline5[] = "-c 'import os, sysconfig; import sys;print(os.path.join(sysconfig.get_config_var(\"LIBDIR\"),\"libpython\"+sys.version[:3]+\".so\"))'"; PetscBool found = PETSC_FALSE; PetscFunctionBegin; #if defined(PETSC_PYTHON_LIB) CHKERRQ(PetscStrncpy(pythonlib,PETSC_PYTHON_LIB,pl)); PetscFunctionReturn(0); #endif CHKERRQ(PetscPythonFindLibraryName(pythonexe,cmdline1,pythonlib,pl,&found)); if (!found) { CHKERRQ(PetscPythonFindLibraryName(pythonexe,cmdline2,pythonlib,pl,&found)); } if (!found) { CHKERRQ(PetscPythonFindLibraryName(pythonexe,cmdline3,pythonlib,pl,&found)); } if (!found) { CHKERRQ(PetscPythonFindLibraryName(pythonexe,cmdline4,pythonlib,pl,&found)); } if (!found) { CHKERRQ(PetscPythonFindLibraryName(pythonexe,cmdline5,pythonlib,pl,&found)); } CHKERRQ(PetscInfo(NULL,"Python library %s found %d\n",pythonlib,found)); PetscFunctionReturn(0); } /* ---------------------------------------------------------------- */ typedef struct _Py_object_t PyObject; /* fake definition */ static PyObject* Py_None = NULL; static const char* (*Py_GetVersion)(void); static int (*Py_IsInitialized)(void); static void (*Py_InitializeEx)(int); static void (*Py_Finalize)(void); static void (*PySys_SetArgv)(int,void*); static PyObject* (*PySys_GetObject)(const char*); static PyObject* (*PyObject_CallMethod)(PyObject*,const char*, const char*, ...); static PyObject* (*PyImport_ImportModule)(const char*); static void (*Py_IncRef)(PyObject*); static void (*Py_DecRef)(PyObject*); static void (*PyErr_Clear)(void); static PyObject* (*PyErr_Occurred)(void); static void (*PyErr_Fetch)(PyObject**,PyObject**,PyObject**); static void (*PyErr_NormalizeException)(PyObject**,PyObject**, PyObject**); static void (*PyErr_Display)(PyObject*,PyObject*,PyObject*); static void (*PyErr_Restore)(PyObject*,PyObject*,PyObject*); #define PetscDLPyLibOpen(libname) \ PetscDLLibraryAppend(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,libname) #define PetscDLPyLibSym(symbol, value) \ PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,symbol,(void**)value) #define PetscDLPyLibClose(comm) \ do { } while (0) static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[]) { PetscFunctionBegin; /* open the Python dynamic library */ CHKERRQ(PetscDLPyLibOpen(pythonlib)); CHKERRQ(PetscInfo(NULL,"Python: loaded dynamic library %s\n", pythonlib)); /* look required symbols from the Python C-API */ CHKERRQ(PetscDLPyLibSym("_Py_NoneStruct" , &Py_None)); CHKERRQ(PetscDLPyLibSym("Py_GetVersion" , &Py_GetVersion)); CHKERRQ(PetscDLPyLibSym("Py_IsInitialized" , &Py_IsInitialized)); CHKERRQ(PetscDLPyLibSym("Py_InitializeEx" , &Py_InitializeEx)); CHKERRQ(PetscDLPyLibSym("Py_Finalize" , &Py_Finalize)); CHKERRQ(PetscDLPyLibSym("PySys_GetObject" , &PySys_GetObject)); CHKERRQ(PetscDLPyLibSym("PySys_SetArgv" , &PySys_SetArgv)); CHKERRQ(PetscDLPyLibSym("PyObject_CallMethod" , &PyObject_CallMethod)); CHKERRQ(PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule)); CHKERRQ(PetscDLPyLibSym("Py_IncRef" , &Py_IncRef)); CHKERRQ(PetscDLPyLibSym("Py_DecRef" , &Py_DecRef)); CHKERRQ(PetscDLPyLibSym("PyErr_Clear" , &PyErr_Clear)); CHKERRQ(PetscDLPyLibSym("PyErr_Occurred" , &PyErr_Occurred)); CHKERRQ(PetscDLPyLibSym("PyErr_Fetch" , &PyErr_Fetch)); CHKERRQ(PetscDLPyLibSym("PyErr_NormalizeException", &PyErr_NormalizeException)); CHKERRQ(PetscDLPyLibSym("PyErr_Display", &PyErr_Display)); CHKERRQ(PetscDLPyLibSym("PyErr_Restore", &PyErr_Restore)); /* XXX TODO: check that ALL symbols were there !!! */ PetscCheck(Py_None,PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: failed to load symbols from Python dynamic library %s",pythonlib); PetscCheck(Py_GetVersion,PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: failed to load symbols from Python dynamic library %s",pythonlib); PetscCheck(Py_IsInitialized,PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: failed to load symbols from Python dynamic library %s",pythonlib); PetscCheck(Py_InitializeEx,PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: failed to load symbols from Python dynamic library %s",pythonlib); PetscCheck(Py_Finalize,PETSC_COMM_SELF,PETSC_ERR_LIB,"Python: failed to load symbols from Python dynamic library %s",pythonlib); CHKERRQ(PetscInfo(NULL,"Python: all required symbols loaded from Python dynamic library %s\n",pythonlib)); PetscFunctionReturn(0); } /* ---------------------------------------------------------------- */ static char PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 }; static char PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 }; static PetscBool PetscBeganPython = PETSC_FALSE; /*@C PetscPythonFinalize - Finalize Python. Level: intermediate @*/ PetscErrorCode PetscPythonFinalize(void) { PetscFunctionBegin; if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); } PetscBeganPython = PETSC_FALSE; PetscFunctionReturn(0); } /*@C PetscPythonInitialize - Initialize Python and import petsc4py. Input Parameter: + pyexe - path to the Python interpreter executable, or NULL. - pylib - full path to the Python dynamic library, or NULL. Level: intermediate @*/ PetscErrorCode PetscPythonInitialize(const char pyexe[],const char pylib[]) { PyObject *module = NULL; PetscFunctionBegin; if (PetscBeganPython) PetscFunctionReturn(0); /* Python executable */ if (pyexe && pyexe[0] != 0) { CHKERRQ(PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe))); } else { CHKERRQ(PetscPythonFindExecutable(PetscPythonExe,sizeof(PetscPythonExe))); } /* Python dynamic library */ if (pylib && pylib[0] != 0) { CHKERRQ(PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib))); } else { CHKERRQ(PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib,sizeof(PetscPythonLib))); } /* dynamically load Python library */ CHKERRQ(PetscPythonLoadLibrary(PetscPythonLib)); /* initialize Python */ PetscBeganPython = PETSC_FALSE; if (!Py_IsInitialized()) { static PetscBool registered = PETSC_FALSE; const char *py_version; PyObject *sys_path; char path[PETSC_MAX_PATH_LEN] = { 0 }; /* initialize Python */ Py_InitializeEx(0); /* 0: do not install signal handlers */ /* build 'sys.argv' list */ py_version = Py_GetVersion(); if (py_version[0] == '2') { int argc = 0; char *argv[1] = {NULL}; PySys_SetArgv(argc,argv); } if (py_version[0] == '3') { int argc = 0; wchar_t *argv[1] = {NULL}; PySys_SetArgv(argc,argv); } /* add PETSC_LIB_DIR in front of 'sys.path' */ sys_path = PySys_GetObject("path"); if (sys_path) { CHKERRQ(PetscStrreplace(PETSC_COMM_SELF,"${PETSC_LIB_DIR}",path,sizeof(path))); Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,(char*)path)); #if defined(PETSC_PETSC4PY_INSTALL_PATH) { char *rpath; CHKERRQ(PetscStrallocpy(PETSC_PETSC4PY_INSTALL_PATH,&rpath)); Py_DecRef(PyObject_CallMethod(sys_path,"insert","is",(int)0,rpath)); CHKERRQ(PetscFree(rpath)); } #endif } /* register finalizer */ if (!registered) { CHKERRQ(PetscRegisterFinalize(PetscPythonFinalize)); registered = PETSC_TRUE; } PetscBeganPython = PETSC_TRUE; } /* import 'petsc4py.PETSc' module */ module = PyImport_ImportModule("petsc4py.PETSc"); if (module) { CHKERRQ(PetscInfo(NULL,"Python: successfully imported module 'petsc4py.PETSc'\n")); Py_DecRef(module); module = NULL; } else { PetscPythonPrintError(); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Python: could not import module 'petsc4py.PETSc', perhaps your PYTHONPATH does not contain it"); } PetscFunctionReturn(0); } /*@C PetscPythonPrintError - Print Python errors. Level: developer @*/ PetscErrorCode PetscPythonPrintError(void) { PyObject *exc=NULL, *val=NULL, *tb=NULL; PetscFunctionBegin; if (!PetscBeganPython) PetscFunctionReturn(0); if (!PyErr_Occurred()) PetscFunctionReturn(0); PyErr_Fetch(&exc,&val,&tb); PyErr_NormalizeException(&exc,&val,&tb); PyErr_Display(exc ? exc : Py_None, val ? val : Py_None, tb ? tb : Py_None); PyErr_Restore(exc,val,tb); PetscFunctionReturn(0); } /* ---------------------------------------------------------------- */ PETSC_EXTERN PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]); PetscErrorCode (*PetscPythonMonitorSet_C)(PetscObject,const char[]) = NULL; /*@C PetscPythonMonitorSet - Set Python monitor Level: developer @*/ PetscErrorCode PetscPythonMonitorSet(PetscObject obj, const char url[]) { PetscFunctionBegin; PetscValidHeader(obj,1); PetscValidCharPointer(url,2); if (!PetscPythonMonitorSet_C) { CHKERRQ(PetscPythonInitialize(NULL,NULL)); PetscCheck(PetscPythonMonitorSet_C,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Couldn't initialize Python support for monitors"); } CHKERRQ(PetscPythonMonitorSet_C(obj,url)); PetscFunctionReturn(0); } /* ---------------------------------------------------------------- */