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: /* ---------------------------------------------------------------- */