[Python-Dev] Initialization hook for extenders

Patrick J. Miller patmiller@llnl.gov
Wed, 30 Apr 2003 15:15:31 -0700


This is a multi-part message in MIME format.
--------------42714FBF141F967516679964
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I work on several projects that have initialization requirements that
need to grab control after Py_Initialize(), but before any user code
runs (via input, script, -c, etc...).

Note that these are Python clones that take advantage of an installed
python (using its $prefix/lib/pythonx.x/*.py and site-packages/*)

We could use 

PyImport_AppendInittab("sitecustomize",initsitecustomize);

But if there already IS customization in sitecustomize.py, I've
blown it away (and have to look it up and force an import).
And if someone uses the -S flag, I'm screwed.

I propose a hook styled after Py_AtExit(func) called Py_AtInit(func)
which maintains a list of functions that are called in Py_Initialize
right after main and site initializations.

If the hook isn't used, then the cost is a single extra function
call at initialization.  Here's a spurious example:  A customer wants
a version of python that has all the math functions and his
extensions to act like builtins...

I would write (without refcnt or error checks ;-):

#include "Python.h"
static void after_init(void) {
    PyObject *builtin,*builtin_dict,*math,*math_dict,*user,*user_dict;

    builtin = PyImport_ImportModule("__builtin__");
    builtin_dict = PyModule_GetDict(builtin);
    math = PyImport_ImportModule("math");
    math_dict = PyModule_GetDict(math);
    user = PyImport_ImportModule("user");
    user_dict = PyModule_GetDict(math);

    PyDict_Update(builtin_dictionary, math_dict);
    PyDict_Update(builtin_dictionary, user_dict);
}


int main(int argc, char** argv) {
    PyImport_AppendInittab("user",inituser);
    Py_AtInit(after_init);

    return Py_Main(argc, argv);
}

voila!  An extended Python with new builtins.

I actually want this to do some MPI initialization to setup a
single user prompt with broadcast which has to run after
Py_Initialize() but before the import of readline.

I've attached a copy of the patch (also going to patches
at sf.net)

Pat


-- 
Patrick Miller | (925) 423-0309 |
http://www.llnl.gov/CASC/people/pmiller

Son, when you grow up you will know who I really am.
I am just a child like you who has been forced to act
responsibly.  -- Rod Byrnes
--------------42714FBF141F967516679964
Content-Type: text/plain; charset=us-ascii;
 name="Py_AtInit.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Py_AtInit.diff"

Index: dist/src/Include/pythonrun.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/pythonrun.h,v
retrieving revision 2.62
diff -c -r2.62 pythonrun.h
*** dist/src/Include/pythonrun.h	13 Feb 2003 22:07:52 -0000	2.62
--- dist/src/Include/pythonrun.h	30 Apr 2003 22:04:13 -0000
***************
*** 75,80 ****
--- 75,81 ----
  PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *);
  
  PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
+ PyAPI_FUNC(int) Py_AtInit(void (*func)(void));
  
  PyAPI_FUNC(void) Py_Exit(int);
  
Index: dist/src/Python/pythonrun.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v
retrieving revision 2.193
diff -c -r2.193 pythonrun.c
*** dist/src/Python/pythonrun.c	22 Apr 2003 11:18:00 -0000	2.193
--- dist/src/Python/pythonrun.c	30 Apr 2003 22:04:16 -0000
***************
*** 106,111 ****
--- 106,135 ----
  	return flag;
  }
  
+ #define NINITFUNCS 32
+ static void (*initfuncs[NINITFUNCS])(void);
+ static int ninitfuncs = 0;
+ 
+ int Py_AtInit(void (*func)(void))
+ {
+ 	if (ninitfuncs >= NINITFUNCS)
+ 		return -1;
+ 	if (!func)
+ 		return -1;
+ 	initfuncs[ninitfuncs++] = func;
+ 	return 0;
+ }
+ 
+ static void initinitialize(void)
+ {
+ 	int i;
+ 	for(i=0;i<ninitfuncs;++i) {
+ 		initfuncs[i]();
+ 		if (PyErr_Occurred())
+ 		  Py_FatalError("Py_AtInit: initialization error");
+ 	}
+ }
+ 
  void
  Py_Initialize(void)
  {
***************
*** 182,190 ****
--- 206,217 ----
  	initsigs(); /* Signal handling stuff, including initintr() */
  
  	initmain(); /* Module __main__ */
+ 
  	if (!Py_NoSiteFlag)
  		initsite(); /* Module site */
  
+ 	initinitialize(); /* Extenstion hooks */
+ 
  	/* auto-thread-state API, if available */
  #ifdef WITH_THREAD
  	_PyGILState_Init(interp, tstate);
***************
*** 1418,1423 ****
--- 1445,1451 ----
  #endif /* MS_WINDOWS */
  	abort();
  }
+ 
  
  /* Clean up and exit */
  

--------------42714FBF141F967516679964--