Actual source code: pythonsys.c
petsc-3.9.2 2018-05-20
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: /* ---------------------------------------------------------------- */