[mod_python] Initializing the interpreter in python_init() instead of python_handler()

Jack Diederich jack_diederich at email.com
Mon Sep 16 13:19:25 EST 2002


I just threw some of the python_handler() code into python_init() and it works!

This means that it is possible to do all the imports etc only once, instead of once per child.
I mentioned the possibility here
http://www.modpython.org/pipermail/mod_python/2002-July/002246.html
and compared it to the mod_perl handler here
http://www.modpython.org/pipermail/mod_python/2002-July/002248.html

Basically, we currently do more work than we have to because each child does the same work to initalize the interpreter.  In the easy case where we are using the PythonInterpreter directive to force everyone to use
the same name for the interpreter (in the below example 'MAIN') we can just do the one initilization in python_init() and the children inherit a clone of the result.  I'm not aware of any problems this might cause (wierd shared file handles or something) but I haven't tested it very extensively.  I do some calculations in the main of several of my modules, so having this done once is a decent speed boost at apache startup.

below is my replacement python_init(), it only works if you have

PythonInterpreter 'MAIN'

in your httpd.conf

modified python_init follows, based on ver 2.7.8
GLYPHS AND WARNINGS!
this is just a proof-of-concept, I don't do lots of neccessary error checking
and I've hard coded all my strings instead of reading the apache configuration.
After initializing the MAIN interpreter, it loads my module your_python_module_here.py
and calls its setup function do_our_one_time_global_setup().  The children then get all
the calculated stuff that was done in do_our_one_time_global_setup().

enjoy,

-jack

void python_init(server_rec *s, pool *p)
{

    char buff[255];
    PyObject *m;
    PyObject *obCallBack = NULL;
    interpreterdata *idata;
    PyThreadState *tstate;

    /* pool given to us in ChildInit. We use it for 
       server.register_cleanup() */
    pool *child_init_pool = NULL;

    /* mod_python version */
    ap_add_version_component(VERSION_COMPONENT);
    
    /* Python version */
    sprintf(buff, "Python/%s", strtok((char *)Py_GetVersion(), " "));
    ap_add_version_component(buff);

    /* initialize global Python interpreter if necessary */
    if (! Py_IsInitialized()) 
    {

	/* initialze the interpreter */
	Py_Initialize();

#ifdef WITH_THREAD
	/* create and acquire the interpreter lock */
	PyEval_InitThreads();
#endif
	/* Release the thread state because we will never use 
	 * the main interpreter, only sub interpreters created later. */
        PyThreadState_Swap(NULL); 

	/* create the obCallBack dictionary */
	interpreters = PyDict_New();
	if (! interpreters) {
	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
			 "python_init: PyDict_New() failed! No more memory?");
	    exit(1);
	}

	/* NEW STUFF FROM HERE */
	idata = get_interpreter_data("MAIN", s);
	tstate = PyThreadState_New(idata->istate);
	PyThreadState_Swap(tstate);

	m = PyImport_ImportModule("your_python_module_here");
	if (!m) {
	  fprintf(stderr, "Couldn't import module\n");
	} else {
	  obCallBack = PyObject_CallMethod(m, "do_our_one_time_global_setup", NULL);
	  if (!obCallBack)
	    fprintf(stderr, "CallFunc failed\n");
	  else
	    fprintf(stderr, "I think it succeeded?\n");
	}

	PyThreadState_Swap(NULL);
	PyThreadState_Delete(tstate);
	/* TO HERE */

#ifdef WITH_THREAD
	/* release the lock; now other threads can run */
	PyEval_ReleaseLock();
#endif
    }
}



-- 
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup




More information about the Mod_python mailing list