mod_pythonメモ

http://www.python.jp/doc/contrib/modpython/installation.htmlを試してみました。

Python version mismatch, expected '2.5.1', found '2.6.2'.

とか

[Sat May 23 23:24:37 2009] [error] [client ::1] mod_python (pid=9312, interpreter='Macintosh-6.local', phase='PythonHandler', ha
ndler='mptest'): Application error
[Sat May 23 23:24:37 2009] [error] [client ::1] ServerName: 'Macintosh-6.local'
[Sat May 23 23:24:37 2009] [error] [client ::1] DocumentRoot: '/usr/local/apache2/htdocs'
[Sat May 23 23:24:37 2009] [error] [client ::1] URI: '/test/mptest.py'
[Sat May 23 23:24:37 2009] [error] [client ::1] Location: None
[Sat May 23 23:24:37 2009] [error] [client ::1] Directory: '/usr/local/apache2/htdocs/test/'
[Sat May 23 23:24:37 2009] [error] [client ::1] Filename: '/usr/local/apache2/htdocs/test/mptest.py'
[Sat May 23 23:24:37 2009] [error] [client ::1] PathInfo: ''
[Sat May 23 23:24:37 2009] [error] [client ::1] Traceback (most recent call last):
[Sat May 23 23:24:37 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 1537, in
 HandlerDispatch\n    default=default_handler, arg=req, silent=hlist.silent)
[Sat May 23 23:24:37 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 1202, in
 _process_target\n    module = import_module(module_name, path=path)
[Sat May 23 23:24:37 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 304, in 
import_module\n    return __import__(module_name, {}, {}, ['*'])
[Sat May 23 23:24:37 2009] [error] [client ::1] ImportError: No module named mptest
[Sat May 23 23:24:39 2009] [error] [client ::1] mod_python (pid=9309, interpreter='Macintosh-6.local', phase='PythonHandler', ha
ndler='mptest'): Application error
[Sat May 23 23:24:39 2009] [error] [client ::1] ServerName: 'Macintosh-6.local'
[Sat May 23 23:24:39 2009] [error] [client ::1] DocumentRoot: '/usr/local/apache2/htdocs'
[Sat May 23 23:24:39 2009] [error] [client ::1] URI: '/test/mptest.py'
[Sat May 23 23:24:39 2009] [error] [client ::1] Location: None
[Sat May 23 23:24:39 2009] [error] [client ::1] Directory: '/usr/local/apache2/htdocs/test/'
[Sat May 23 23:24:39 2009] [error] [client ::1] Filename: '/usr/local/apache2/htdocs/test/mptest.py'
[Sat May 23 23:24:39 2009] [error] [client ::1] PathInfo: ''
[Sat May 23 23:24:39 2009] [error] [client ::1] Traceback (most recent call last):
[Sat May 23 23:24:39 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 1537, in
 HandlerDispatch\n    default=default_handler, arg=req, silent=hlist.silent)
[Sat May 23 23:24:39 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 1202, in
 _process_target\n    module = import_module(module_name, path=path)
[Sat May 23 23:24:39 2009] [error] [client ::1]   File "/Library/Python/2.5/site-packages/mod_python/importer.py", line 304, in 
import_module\n    return __import__(module_name, {}, {}, ['*'])
[Sat May 23 23:24:39 2009] [error] [client ::1] ImportError: No module named mptest

とかいわれてはまりました。。。

とりあえずport経由じゃなくてインストールしたPython2.6を削除して、pythonスクリプトをhtdocs直下においたらうまくいきました。以下は作業記録です。

mod_pythonのインストール

$ wget http://ftp.riken.jp/net/apache/httpd/modpython/mod_python-3.3.1.tgz
$ tar zxvf mod_python-3.3.1.tgz
$ cd mod_python-3.3.1
$ ./configure --with-apxs=/usr/local/apache2/bin/apxs --with-python=/usr/bin/python
$ make
$ sudo make install

httpd.confの編集

LoadModule python_module         modules/mod_python.so

<Directory /usr/local/apache2/htdocs/>
  AddHandler mod_python .py
  PythonHandler mptest
  PythonDebug On
</Directory>

動かすpythonスクリプト

$ cat /usr/local/apache2/htdocs/mptest.py 
from mod_python import apache

def handler(req):
    req.write("Hello World!")
    return apache.OK

アクセスするURLはhttp://localhost/mptest.py

gdbデバッグすると以下のような感じ。

$ sudo gdb /usr/local/apache2/bin/httpd
Password:
GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries ........ done

(gdb) b python_handler
Function "python_handler" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (python_handler) pending.
(gdb) r -X
Starting program: /usr/local/apache2/bin/httpd -X
Reading symbols for shared libraries +++++++. done
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done
Reading symbols for shared libraries .. done
Breakpoint 1 at 0x21865a: file mod_python.c, line 1533.
Pending breakpoint 1 - "python_handler" resolved
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done
Reading symbols for shared libraries .. done
Breakpoint 1 at 0x21865a: file mod_python.c, line 1533.
Pending breakpoint 1 - "python_handler" resolved

Breakpoint 1, 0x0021865a in python_handler (req=0x8fd050, phase=0x21d960 "PythonInitHandler") at mod_python.c:1533
1533	{
(gdb) l
1528	 **
1529	 *      A generic python handler. Most handlers should use this.
1530	 */
1531	
1532	static int python_handler(request_rec *req, char *phase)
1533	{
1534	
1535	    PyObject *resultobject = NULL;
1536	    interpreterdata *idata;
1537	    requestobject *request_obj;
(gdb) n
1535	    PyObject *resultobject = NULL;
(gdb) n
1540	    const char *interp_name = NULL;
(gdb) bt
#0  python_handler (req=0x8fd050, phase=0x21d960 "PythonInitHandler") at mod_python.c:1540
#1  0x0021afa6 in PythonPostReadRequestHandler (req=0x8fd050) at mod_python.c:2898
#2  0x0001c113 in ap_run_post_read_request ()
#3  0x0001a95b in ap_read_request ()
#4  0x0003a41e in ap_process_http_connection ()
#5  0x00012c0d in ap_run_process_connection ()
#6  0x00013089 in ap_process_connection ()
#7  0x000586ff in child_main ()
#8  0x0005881c in make_child ()
#9  0x00058eb9 in ap_mpm_run ()
#10 0x0000a9d5 in main ()
(gdb) c
Continuing.

mod_python.cのpython_handler関数をちろっとみるとget_interpreterインタープリタを取得してPyObject_CallMethodでpythonスクリプトを起動してrelease_interpreterインタープリタを解放してるっぽい。

1627     /* get/create interpreter */
1628     idata = get_interpreter(interp_name);
1629 
1630     if (!idata) {
1631         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, req,
1632                       "python_handler: Can't get/create interpreter.");
1633         return HTTP_INTERNAL_SERVER_ERROR;
1634     }
1635     
1636     /* create/acquire request object */
1637     request_obj = python_get_request_object(req, phase);
1638 
1639     /* remember the extension if any. used by publisher */
1640     if (ext) 
1641         request_obj->extension = apr_pstrdup(req->pool, ext);
1642 
1643     /* construct a new handler list object */
1644     Py_XDECREF(request_obj->hlo);
1645     request_obj->hlo = (hlistobject *)MpHList_FromHLEntry(hlohle);
1646 
1647     /* 
1648      * Here is where we call into Python!
1649      * This is the C equivalent of
1650      * >>> resultobject = obCallBack.Dispatch(request_object, phase)
1651      */
1652     resultobject = PyObject_CallMethod(idata->obcallback, "HandlerDispatch",
1653                                        "O", request_obj);
1654 
1655     /* clear phase from request object */
1656     Py_XDECREF(request_obj->phase);
1657     request_obj->phase = NULL;
1658 
1659     /* release the lock and destroy tstate*/
1660     release_interpreter();