首页 > 代码库 > mod_python模块安装使用

mod_python模块安装使用


二、mod_python


1.性能

使用mod_python的主要优势在于比传统CGI更高的性能
一个测试,使用在Pentium 1.2GHz的机器上运行Red Hat Linux 7.3。使用4种类型的脚本,基于标准的CGI导入模块(以典型的Python CGI脚本开始),然后输出‘Hello!‘,测试10000次请求作为基准。

标准CGI 23 次请求/

mod_python CGI处理器: 385 次请求/

mod_python 发布处理器: 476 次请求/

mod_python 处理器: 1203 次请求/




2.安装

参考:http://galean.blog.51cto.com/7702012/1302140
          http://wiki.woodpecker.org.cn/moin/modpythoncn

本文是参考以上两个技术文档,自己实际操作后的总结。

mod_python要与Apache协同工作

下载:http://modpython.org

[root@www local]# cd mod_python-3.3.1/ 
[root@www mod_python-3.3.1]# ls 
configure CREDITS doc-html lib NEWS src 
configure.in dist examples LICENSE NOTICE test 
COPYRIGHT Doc install-sh Makefile.in README 
[root@www mod_python-3.3.1]# find / -name apxs 
/usr/sbin/apxs 
[root@www mod_python-3.3.1]# ./configure --with-apxs=/usr/sbin/apxs


出错:
configure: error: Can not link to python
解决:
yum install python-devel



[root@www mod_python-3.3.1]# make


如果在编译的过程中出现了如下错误:

connobject.c:142: error: request for member ?.ext?.in something not a structure or union

apxs:Error: Command failed with rc=65536

make[1]: *** [mod_python.so] Error 1

make[1]: Leaving directory `/usr/local/src/mod_python-3.3.1/src‘

make: *** [do_dso] Error 2

需要修改/mod_python-3.3.1/src/connobject.c这个文件,将其中的“!(b == APR_BRIGADE_SENTINEL(b) ”

修改为 “!(b == APR_BRIGADE_SENTINEL(bb)”


[root@www mod_python-3.3.1]# make install


[root@www mod_python-3.3.1]# find / -name mod_python.so 
/usr/lib/httpd/modules/mod_python.so 
/usr/local/mod_python-3.3.1/src/.libs/mod_python.so 
/usr/local/mod_python-3.3.1/src/mod_python.so 
[root@www mod_python-3.3.1]# 

然后检查apache的modules目录是否存在mod_python.so库,如果不存在,拷贝/usr/local/src/mod_python-3.3.1/src/mod_python.so到apache的modules目录。

并在httpd.conf中加入:

LoadModule python_module modules/mod_python.so




3.测试


配置httpd.conf文件


在httpd.conf中加入:

<Directory "/var/www/html/pyweb">

 AllowOverride FileInfo

 AddHandler mod_python .py

 PythonHandler index

 PythonDebug On

 Order allow,deny

 Allow from all

</Directory>




[root@www pyweb]# cat index.py   这里要是index.py才能正常显示,因为 PythonHandler index 指定了模块名
#!/usr/bin/python 
from mod_python import apache 
def handler(req): 
    req.content_type=‘text/plain‘ 

    req.write("Hello, world!") 
    return apache.OK 
[root@www pyweb]# 

(注意:PythonHandler index ,这里的名字index决定必须用index.py来测试)


解释一下这个程序:


addHandler 指示告诉 apache, 所有在/var/www/html/pyweb 目录或者是它的子目录下的所有.py文件,有关于这些文件的任何请求都用mod_python 来处理, PythonHandler index  指示告诉 mod_python 用 index  执行默认的处理器. “pythonDebug On” 指示告诉mod_python如果发生错误,就把错误信息打印到客户端 (相对于写入日志文件),在开发的时候这个选项非常有用。

当一个请求发出时,apache通过调用mod_python中的处理器分步处理请求,Mod_python首先检查请求的那个处理器是否在配置文件中指定了(记住,它的角色是发报机dispatcher),在我们的例子中,mod_python除了调用默认的那个处理器外不会调用其他的任何处理器,然后,mod_python会发现"PythonHandler index  "指示,并按照下面的步骤来进行:


1.如果以前没有做过,那么就把pythonHandler指定的那个目录加到sys.path中。

2.尝试引入index  的模块(注意,如果index 在pythonHandler指定那个目录的子目录中的话,引入会出错,因为子目录并没有加到sys.path中,解决这种情况的方法是使用包)例如:”pythonHandler subdir.index ”

3.在index 中寻找名字叫handler的方法。

4.调用这个方法,并把request对象传递给它。

5.现在让我们深入这段脚本看一下:

from mod_python import apache 

这个引入语句提供给我们一个访问apache的接口。除了极少数情况外,每一个mod_python程序一般都会有这一行。

def handler(req): 

这是处理器方法的声明,它之所以叫"handler"是因为mod_python在指示中使用这个名字,转换它为小写并移除"python",所以"pythonHandler"变成了"handler",你可以给它起别的名字,并且通过在指示中使用"::"明确的指定它.举个例子,如果处理器方法叫"spam",那么指示就应该是”pythonHandler myscript::spam”。

注意处理器必须有一个参数


request对象。Request对象提供了所有可能用到的信息,比如客户端的IP,头,URI等等.返回客户端的信息仍然通过request对象传递,注意,在mod_python中没有response对象。

req.content_type = "text/plain" 

这条语句设置文档类型为” text/plain”。默认的通常是” text/html”,但是因为我们的处理器不处理任何html, 所以“text/plain”更合适一些。

req.write("Hello World!") 

这条语句把字符串” Hello World!”写到客户端(再次强调没有response对象,所以写到客户端仍然有request对象)。

return apache.OK 

这条语句告诉apache一切正常,而且请求也已经被处理了。如果出现异常,这一行应该返回apache.HTTP INTERNAL SERVER ERROR或返回apache.HTTP FORBIDDEN,而且apache会在日志中记录这个错误,并产生一条错误信息给客户端。

一些提示:如果你仔细阅读的话,就会发现URI只是指向了index.py这个文件,并没有指定处理器代码执行的顺序,实际上只要告诉处理器需要处理的是一个.py文件就可以了,文件的名字并不重要,即使URL中指向的文件并不存在.所以,对于上面的配置,http://myserver/mywebdir/index.py 和 http://myserver/mywebdir/test.py 执行的结果是一样的。






调试出现以下错误,原因是没有缩进:
IndentationError: expected an indented block  

当我重新创建一个test.py文件的时候,内容不同,但是结果显示的内容却是index.py的内容。

于是觉得是config文件中 PythonHandler index的影响,去掉该行之后无法解析了。




配置.htaccess文件

在官方的说明中,.htaccess是网站的一个分布式配置文件,分布式顾名思义,就是可以分布在各个不同的目录下面,每个文件都有其不同的作用域。比如将文件放在“admin”目录下,那么这个配置文件只对admin及其子目录下的文件生效。

没有配置成功,加入以下内容没有起到效果:

 AllowOverride FileInfo 
 AddHandler mod_python .py 
 PythonHandler index 
 PythonDebug On





为什么要使用mod_python模块?????

事实上,mod_python是在Apache Web服务器中嵌入了具有全部功能的Python解释器。这个模块通常被用来强劲而高效地产生动态网页,当然它还有一些其他的用途。 编写mod_python程序在很多方面和编写CGI程序类似,所以熟悉CGI(详见第18章)会对您学习mod_python有很大的帮助。mod_python和CGI之间也有不同的地方,在本章中,我们也将介绍这些不同。 19.1  理解为什么需要mod_python 我们已经在第18章中讨论过,CGI脚本是最常用的一种产生动态网页的方法。每当有页面请求的时候,对应的CGI脚本就被调用。它读取请求,产生应答,并最终终止。这是仿效HTTP的操作,后者的核心是一次为一个单一的请求服务。下一次又有请求的时候,CGI脚本会被重新调用,这样的设计就使CGI脚本具有语言和服务器中立的特性;而且事实上,所有流行的Web服务器和程序语言都支持CGI。 然而,这种兼容性是有代价的:那就是性能。启动一个CGI脚本很慢,操作系统需要为它建立新进程。Python解释器需要初始化和载入脚本。对于连接数据库的CGI脚本来说,性能就更差了,因为每次显示一个页面的时候,它们都必须建立一个新的数据库session。正是因为这个原因,CGI脚本不适合那些流量大的站点。 mod_python就是一个解决这个问题的方法。它实际上在Apache Web服务器中嵌入了一个完整的Python解释器。CGI脚本只在服务器进程初始化的时候载入一次。数据库连接也可以在Web服务器初始化的时候建立,并保持连接直到Web服务器关闭。每当要产生一个页面的时候,一个特殊的函数就被调用,所有关于请求的数据都被传入该函数。这个函数有权访问Web服务器初始化时建立的环境变量。例如,它可以重复使用已经存在的数据库连接。 尽管这种方法必须使用Apache服务器,但是它的优点要比缺点多得多,尤其是当您从头开始设计一个完整的Web应用的时候。Python可以作为那些专门开发Web应用语言的替代者,例如PHP。 事实上,mod_python除了用在提供页面之外还可以做其他的事情。它还可以在多个方面和Apache系统结合。例如:Apache提供了多种认证的处理方法,这些方法可以使您根据一个包含用户名和密码的文本文件或LDAP数据库来认证用户。您可以使用mod_python来编写您自己的认证处理程序(或许它通过一个远程XML-RPC服务器来验证),并随时在Apache中使用这个程序——即使是那些不是由Python代码产生的页面。





4.使用发布器(Publisher)的快速例子


发布器(publisher)提供了发布mod_python标准模块的方式。需要在配置文件中加入如下配置:

[root@www pyweb]# tail -7 /etc/httpd/conf/httpd.conf

<Directory "/var/www/html/pyweb/"> 
        AddHandler mod_python .py 
        PythonHandler mod_python.publisher 
        PythonDebug On 
</Directory> 


经测试发现可以同时多个 PythonHandler处理器一起使用,只是结果都会出现在同一页面。如下便是publisher和index测试同时配置了PythonHandler的结果




简单举例:
接下来的这个例子展示了一个简单的返回表单,这个表单询问用户的名称,电子邮箱,地址和意见,然后发送一封电子邮件给网络管理员,信的内容就是用户填写的意见。这个简单的程序包括两个文件:form.html---用来收集数据,form.py---表单的action指令发送的目标。

[root@www pyweb]# cat form.html 
<html>
   请填写下面的回馈表单:
   <form action="form.py/email" method="POST">
          用户名: <input type="text" name="name"><br>
          电子邮件: <input type="text" name="email"><br>
          意见: <textarea name="comment" rows=4 cols=20></textarea><br>
                    <input type="submit">
     </form>
</html>


[root@www pyweb]# cat form.py
#!/usr/bin/python
#-*- coding: UTF-8 -*-
import smtplib
from mod_python import apache
WEBMASTER = "webmaster"        # webmaster e-mail
SMTP_SERVER = "localhost"      # your SMTP server
def email(req, name, email, comment):
     #确定用户提供了所有的参数
    if not (name and email and comment):
        return "A required parameter is missing,please go back and correct the error"
            # 创建消息对话框
    msg = """\
           From: %s
           Subject: feedback
           To: %s
           I have the following comment:
           %s
              Thank You,
           %s
    """ % (email, WEBMASTER, comment, name)
    #发出信件
    conn = smtplib.SMTP(SMTP_SERVER)
    conn.sendmail(email, [WEBMASTER], msg)
    conn.quit()

    # 返回用户信息
    s = """\
       <html>
       亲爱的%s,<br>
       谢谢你的意见,我们会在近期与你联系.
       </html>
    """ % name
    return s


[root@www pyweb]# cat /var/spool/mail/root
From 171285755@qq.com Tue Jun 17 14:29:18 2014
Return-Path: <171285755@qq.com>
X-Original-To: webmaster
Delivered-To: webmaster@www.tqy.com
Received: from www.tqy.com (localhost [IPv6:::1])
        by www.tqy.com (Postfix) with ESMTP id 292EE1617
        for <webmaster>; Tue, 17 Jun 2014 14:29:18 +0800 (CST)
Message-Id: <20140617062918.292EE1617@www.tqy.com>
Date: Tue, 17 Jun 2014 14:29:18 +0800 (CST)
From: 171285755@qq.com
To: undisclosed-recipients:;
           From: 171285755@qq.com
           Subject: feedback
           To: webmaster
           I have the following comment:
           试试
              Thank You,
           tqy-test



当用户点击确定按钮的时候,发布处理器就会调用form模块中的email方法,把表单中各个域的值做为email方法的参数传递给email方法,并且也会把request的对象req一并传递过去。


并不是非要把req做为email方法的一个参数不可,如果你不需要它,可以省略掉。发布处理器很灵活,它只会把那些在方法的参数列表中存在参数所相对应的域的值传递过去。
方法的返回值在浏览器中显示出来。


虽然发布处理器极大的简化了mod_python编程,但是mod_python所具有的强大功能却没有损失,因为发布处理器可以访问到request对象,所以你可以做到与原生(native)mod_python处理器完全相同的事情。 举例来说:
通过req.headers可以自定义头(header),通过抛出apache.SERVERERROR返回异常,通过req.write()和req.read()直接读写客户端等等。






错误:SyntaxError: Non-ASCII character ‘\xe7‘ in file 


出现这种错误的原因是程序中的编码出问题了,只要在程序的最前面加上

 

 #-*- coding: UTF-8 -*- 

 重新保存即可



5.认证

假设我们想用密码保护一个目录,用名字:spam,密码:eggs来登陆。

首先,我们需要告诉apache当需要认证的时候去调用我们的认证处理器。我们通过在配置文件中加入pythonAuthenHandler来实现,如下:


[root@www pyweb]# tail -11 /etc/httpd/conf/httpd.conf
<Directory "/var/www/html/pyweb/"> 
        AddHandler mod_python .py 
        #PythonHandler mod_python.publisher   #加上该句则输入用户名和密码之后报错无法找到myscript.py文件
        PythonHandler myscript                #我们在这里为两个不同的处理器指定了相同的脚本,这是可以的 
        PythonAuthenHandler myscript 
        PythonDebug On 
        AuthType Basic 
        AuthName "Restricted Area" 
        require valid-user 
</Directory> 
[root@www pyweb]#


[root@www pyweb]# cat myscript.py  
#!/usr/bin/python 
from mod_python import apache 
def authenhandler(req):                      #处理器方法的声明 
    req.content_type=‘text/plain‘ 
    pw = req.get_basic_auth_pw() 
    user = req.user 
    if user == "spam" and pw == "eggs": 
        return apache.OK 
    else: 
        return apache.HTTP_UNAUTHORIZED 
def handler(req): 
    req.content_type=‘text/html‘ 
    req.write("Hello, world!---test") 
    return apache.OK 
[root@www pyweb]# 

执行authenhandler成功则会继续执行以下handler内容,否则会返回错误信息。



authenhandler(req)

为什么这个方法的名字叫authenhandler呢?mod_python把配置文件中的指示的名称(pythonAuthenHandler)去掉"python",然后把剩下的单词全部变成小写,因此就是authenhandler了。

pw = req.get_basic_auth_pw()

我们通过这一句代码得到密码。http在传输验证密码的时候一般以base64的编码进行传输,这个方法把它解析成字符串。



其他处理程序:

CGI处理程序所需配置
SetHandler mod_python
PythonHandler mod_python.cgihandler

apache配置支持PSP
AddHandler mod_python .psp
PythonHandler mod_python.psp



6.psp处理程序

html和python代码的混合使用
psp处理程序用<%%>包括

[root@www psp]# vi index.psp
<%
from random import choice
adjectives = [‘beatiful‘,‘cruel‘]
%>
<html>
   <head>
     <title>hello</title>
   </head>
        <body>
        <p>hello.<%=choice(adjectives)%> girl. my name is ***</p>
        </body>
</html>
A <%
for i in range(3):
  %>
  merry.
<%
%>

merry christamas time. 

结果显示:

hello.beatiful girl. my name is ***

A merry. merry. merry. merry christamas time.


<% %>空的用来终止该for块,不然下面的信息也会输出三次
二、mod_python


1.性能

使用mod_python的主要优势在于比传统CGI更高的性能
一个测试,使用在Pentium 1.2GHz的机器上运行Red Hat Linux 7.3。使用4种类型的脚本,基于标准的CGI导入模块(以典型的Python CGI脚本开始),然后输出‘Hello!‘,测试10000次请求作为基准。

标准CGI 23 次请求/

mod_python CGI处理器: 385 次请求/

mod_python 发布处理器: 476 次请求/

mod_python 处理器: 1203 次请求/




2.安装

参考:http://galean.blog.51cto.com/7702012/1302140
          http://wiki.woodpecker.org.cn/moin/modpythoncn

本文是参考以上两个技术文档,自己实际操作后的总结。

mod_python要与Apache协同工作

下载:http://modpython.org

[root@www local]# cd mod_python-3.3.1/ 
[root@www mod_python-3.3.1]# ls 
configure CREDITS doc-html lib NEWS src 
configure.in dist examples LICENSE NOTICE test 
COPYRIGHT Doc install-sh Makefile.in README 
[root@www mod_python-3.3.1]# find / -name apxs 
/usr/sbin/apxs 
[root@www mod_python-3.3.1]# ./configure --with-apxs=/usr/sbin/apxs


出错:
configure: error: Can not link to python
解决:
yum install python-devel



[root@www mod_python-3.3.1]# make


如果在编译的过程中出现了如下错误:

connobject.c:142: error: request for member ?.ext?.in something not a structure or union

apxs:Error: Command failed with rc=65536

make[1]: *** [mod_python.so] Error 1

make[1]: Leaving directory `/usr/local/src/mod_python-3.3.1/src‘

make: *** [do_dso] Error 2

需要修改/mod_python-3.3.1/src/connobject.c这个文件,将其中的“!(b == APR_BRIGADE_SENTINEL(b) ”

修改为 “!(b == APR_BRIGADE_SENTINEL(bb)”


[root@www mod_python-3.3.1]# make install


[root@www mod_python-3.3.1]# find / -name mod_python.so 
/usr/lib/httpd/modules/mod_python.so 
/usr/local/mod_python-3.3.1/src/.libs/mod_python.so 
/usr/local/mod_python-3.3.1/src/mod_python.so 
[root@www mod_python-3.3.1]# 

然后检查apache的modules目录是否存在mod_python.so库,如果不存在,拷贝/usr/local/src/mod_python-3.3.1/src/mod_python.so到apache的modules目录。

并在httpd.conf中加入:

LoadModule python_module modules/mod_python.so




3.测试


配置httpd.conf文件


在httpd.conf中加入:

<Directory "/var/www/html/pyweb">

 AllowOverride FileInfo

 AddHandler mod_python .py

 PythonHandler index

 PythonDebug On

 Order allow,deny

 Allow from all

</Directory>




[root@www pyweb]# cat index.py   这里要是index.py才能正常显示,因为 PythonHandler index 指定了模块名
#!/usr/bin/python 
from mod_python import apache 
def handler(req): 
    req.content_type=‘text/plain‘ 

    req.write("Hello, world!") 
    return apache.OK 
[root@www pyweb]# 

(注意:PythonHandler index ,这里的名字index决定必须用index.py来测试)


解释一下这个程序:


addHandler 指示告诉 apache, 所有在/var/www/html/pyweb 目录或者是它的子目录下的所有.py文件,有关于这些文件的任何请求都用mod_python 来处理, PythonHandler index  指示告诉 mod_python 用 index  执行默认的处理器. “pythonDebug On” 指示告诉mod_python如果发生错误,就把错误信息打印到客户端 (相对于写入日志文件),在开发的时候这个选项非常有用。

当一个请求发出时,apache通过调用mod_python中的处理器分步处理请求,Mod_python首先检查请求的那个处理器是否在配置文件中指定了(记住,它的角色是发报机dispatcher),在我们的例子中,mod_python除了调用默认的那个处理器外不会调用其他的任何处理器,然后,mod_python会发现"PythonHandler index  "指示,并按照下面的步骤来进行:


1.如果以前没有做过,那么就把pythonHandler指定的那个目录加到sys.path中。

2.尝试引入index  的模块(注意,如果index 在pythonHandler指定那个目录的子目录中的话,引入会出错,因为子目录并没有加到sys.path中,解决这种情况的方法是使用包)例如:”pythonHandler subdir.index ”

3.在index 中寻找名字叫handler的方法。

4.调用这个方法,并把request对象传递给它。

5.现在让我们深入这段脚本看一下:

from mod_python import apache 

这个引入语句提供给我们一个访问apache的接口。除了极少数情况外,每一个mod_python程序一般都会有这一行。

def handler(req): 

这是处理器方法的声明,它之所以叫"handler"是因为mod_python在指示中使用这个名字,转换它为小写并移除"python",所以"pythonHandler"变成了"handler",你可以给它起别的名字,并且通过在指示中使用"::"明确的指定它.举个例子,如果处理器方法叫"spam",那么指示就应该是”pythonHandler myscript::spam”。

注意处理器必须有一个参数


request对象。Request对象提供了所有可能用到的信息,比如客户端的IP,头,URI等等.返回客户端的信息仍然通过request对象传递,注意,在mod_python中没有response对象。

req.content_type = "text/plain" 

这条语句设置文档类型为” text/plain”。默认的通常是” text/html”,但是因为我们的处理器不处理任何html, 所以“text/plain”更合适一些。

req.write("Hello World!") 

这条语句把字符串” Hello World!”写到客户端(再次强调没有response对象,所以写到客户端仍然有request对象)。

return apache.OK 

这条语句告诉apache一切正常,而且请求也已经被处理了。如果出现异常,这一行应该返回apache.HTTP INTERNAL SERVER ERROR或返回apache.HTTP FORBIDDEN,而且apache会在日志中记录这个错误,并产生一条错误信息给客户端。

一些提示:如果你仔细阅读的话,就会发现URI只是指向了index.py这个文件,并没有指定处理器代码执行的顺序,实际上只要告诉处理器需要处理的是一个.py文件就可以了,文件的名字并不重要,即使URL中指向的文件并不存在.所以,对于上面的配置,http://myserver/mywebdir/index.py 和 http://myserver/mywebdir/test.py 执行的结果是一样的。






调试出现以下错误,原因是没有缩进:
IndentationError: expected an indented block  

当我重新创建一个test.py文件的时候,内容不同,但是结果显示的内容却是index.py的内容。

于是觉得是config文件中 PythonHandler index的影响,去掉该行之后无法解析了。




配置.htaccess文件

在官方的说明中,.htaccess是网站的一个分布式配置文件,分布式顾名思义,就是可以分布在各个不同的目录下面,每个文件都有其不同的作用域。比如将文件放在“admin”目录下,那么这个配置文件只对admin及其子目录下的文件生效。

没有配置成功,加入以下内容没有起到效果:

 AllowOverride FileInfo 
 AddHandler mod_python .py 
 PythonHandler index 
 PythonDebug On





为什么要使用mod_python模块?????

事实上,mod_python是在Apache Web服务器中嵌入了具有全部功能的Python解释器。这个模块通常被用来强劲而高效地产生动态网页,当然它还有一些其他的用途。 编写mod_python程序在很多方面和编写CGI程序类似,所以熟悉CGI(详见第18章)会对您学习mod_python有很大的帮助。mod_python和CGI之间也有不同的地方,在本章中,我们也将介绍这些不同。 19.1  理解为什么需要mod_python 我们已经在第18章中讨论过,CGI脚本是最常用的一种产生动态网页的方法。每当有页面请求的时候,对应的CGI脚本就被调用。它读取请求,产生应答,并最终终止。这是仿效HTTP的操作,后者的核心是一次为一个单一的请求服务。下一次又有请求的时候,CGI脚本会被重新调用,这样的设计就使CGI脚本具有语言和服务器中立的特性;而且事实上,所有流行的Web服务器和程序语言都支持CGI。 然而,这种兼容性是有代价的:那就是性能。启动一个CGI脚本很慢,操作系统需要为它建立新进程。Python解释器需要初始化和载入脚本。对于连接数据库的CGI脚本来说,性能就更差了,因为每次显示一个页面的时候,它们都必须建立一个新的数据库session。正是因为这个原因,CGI脚本不适合那些流量大的站点。 mod_python就是一个解决这个问题的方法。它实际上在Apache Web服务器中嵌入了一个完整的Python解释器。CGI脚本只在服务器进程初始化的时候载入一次。数据库连接也可以在Web服务器初始化的时候建立,并保持连接直到Web服务器关闭。每当要产生一个页面的时候,一个特殊的函数就被调用,所有关于请求的数据都被传入该函数。这个函数有权访问Web服务器初始化时建立的环境变量。例如,它可以重复使用已经存在的数据库连接。 尽管这种方法必须使用Apache服务器,但是它的优点要比缺点多得多,尤其是当您从头开始设计一个完整的Web应用的时候。Python可以作为那些专门开发Web应用语言的替代者,例如PHP。 事实上,mod_python除了用在提供页面之外还可以做其他的事情。它还可以在多个方面和Apache系统结合。例如:Apache提供了多种认证的处理方法,这些方法可以使您根据一个包含用户名和密码的文本文件或LDAP数据库来认证用户。您可以使用mod_python来编写您自己的认证处理程序(或许它通过一个远程XML-RPC服务器来验证),并随时在Apache中使用这个程序——即使是那些不是由Python代码产生的页面。





4.使用发布器(Publisher)的快速例子


发布器(publisher)提供了发布mod_python标准模块的方式。需要在配置文件中加入如下配置:

[root@www pyweb]# tail -7 /etc/httpd/conf/httpd.conf

<Directory "/var/www/html/pyweb/"> 
        AddHandler mod_python .py 
        PythonHandler mod_python.publisher 
        PythonDebug On 
</Directory> 


经测试发现可以同时多个 PythonHandler处理器一起使用,只是结果都会出现在同一页面。如下便是publisher和index测试同时配置了PythonHandler的结果



简单举例:
接下来的这个例子展示了一个简单的返回表单,这个表单询问用户的名称,电子邮箱,地址和意见,然后发送一封电子邮件给网络管理员,信的内容就是用户填写的意见。这个简单的程序包括两个文件:form.html---用来收集数据,form.py---表单的action指令发送的目标。

[root@www pyweb]# cat form.html 
<html>
   请填写下面的回馈表单:
   <form action="form.py/email" method="POST">
          用户名: <input type="text" name="name"><br>
          电子邮件: <input type="text" name="email"><br>
          意见: <textarea name="comment" rows=4 cols=20></textarea><br>
                    <input type="submit">
     </form>
</html>


[root@www pyweb]# cat form.py
#!/usr/bin/python
#-*- coding: UTF-8 -*-
import smtplib
from mod_python import apache
WEBMASTER = "webmaster"        # webmaster e-mail
SMTP_SERVER = "localhost"      # your SMTP server
def email(req, name, email, comment):
     #确定用户提供了所有的参数
    if not (name and email and comment):
        return "A required parameter is missing,please go back and correct the error"
            # 创建消息对话框
    msg = """\
           From: %s
           Subject: feedback
           To: %s
           I have the following comment:
           %s
              Thank You,
           %s
    """ % (email, WEBMASTER, comment, name)
    #发出信件
    conn = smtplib.SMTP(SMTP_SERVER)
    conn.sendmail(email, [WEBMASTER], msg)
    conn.quit()

    # 返回用户信息
    s = """\
       <html>
       亲爱的%s,<br>
       谢谢你的意见,我们会在近期与你联系.
       </html>
    """ % name
    return s


[root@www pyweb]# cat /var/spool/mail/root
From 171285755@qq.com Tue Jun 17 14:29:18 2014
Return-Path: <171285755@qq.com>
X-Original-To: webmaster
Delivered-To: webmaster@www.tqy.com
Received: from www.tqy.com (localhost [IPv6:::1])
        by www.tqy.com (Postfix) with ESMTP id 292EE1617
        for <webmaster>; Tue, 17 Jun 2014 14:29:18 +0800 (CST)
Message-Id: <20140617062918.292EE1617@www.tqy.com>
Date: Tue, 17 Jun 2014 14:29:18 +0800 (CST)
From: 171285755@qq.com
To: undisclosed-recipients:;
           From: 171285755@qq.com
           Subject: feedback
           To: webmaster
           I have the following comment:
           试试
              Thank You,
           tqy-test



当用户点击确定按钮的时候,发布处理器就会调用form模块中的email方法,把表单中各个域的值做为email方法的参数传递给email方法,并且也会把request的对象req一并传递过去。


并不是非要把req做为email方法的一个参数不可,如果你不需要它,可以省略掉。发布处理器很灵活,它只会把那些在方法的参数列表中存在参数所相对应的域的值传递过去。
方法的返回值在浏览器中显示出来。


虽然发布处理器极大的简化了mod_python编程,但是mod_python所具有的强大功能却没有损失,因为发布处理器可以访问到request对象,所以你可以做到与原生(native)mod_python处理器完全相同的事情。 举例来说:
通过req.headers可以自定义头(header),通过抛出apache.SERVERERROR返回异常,通过req.write()和req.read()直接读写客户端等等。






错误:SyntaxError: Non-ASCII character ‘\xe7‘ in file 


出现这种错误的原因是程序中的编码出问题了,只要在程序的最前面加上

 

 #-*- coding: UTF-8 -*- 

 重新保存即可



5.认证

假设我们想用密码保护一个目录,用名字:spam,密码:eggs来登陆。

首先,我们需要告诉apache当需要认证的时候去调用我们的认证处理器。我们通过在配置文件中加入pythonAuthenHandler来实现,如下:


[root@www pyweb]# tail -11 /etc/httpd/conf/httpd.conf
<Directory "/var/www/html/pyweb/"> 
        AddHandler mod_python .py 
        #PythonHandler mod_python.publisher   #加上该句则输入用户名和密码之后报错无法找到myscript.py文件
        PythonHandler myscript                #我们在这里为两个不同的处理器指定了相同的脚本,这是可以的 
        PythonAuthenHandler myscript 
        PythonDebug On 
        AuthType Basic 
        AuthName "Restricted Area" 
        require valid-user 
</Directory> 
[root@www pyweb]#


[root@www pyweb]# cat myscript.py  
#!/usr/bin/python 
from mod_python import apache 
def authenhandler(req):                      #处理器方法的声明 
    req.content_type=‘text/plain‘ 
    pw = req.get_basic_auth_pw() 
    user = req.user 
    if user == "spam" and pw == "eggs": 
        return apache.OK 
    else: 
        return apache.HTTP_UNAUTHORIZED 
def handler(req): 
    req.content_type=‘text/html‘ 
    req.write("Hello, world!---test") 
    return apache.OK 
[root@www pyweb]# 

执行authenhandler成功则会继续执行以下handler内容,否则会返回错误信息。



authenhandler(req)

为什么这个方法的名字叫authenhandler呢?mod_python把配置文件中的指示的名称(pythonAuthenHandler)去掉"python",然后把剩下的单词全部变成小写,因此就是authenhandler了。

pw = req.get_basic_auth_pw()

我们通过这一句代码得到密码。http在传输验证密码的时候一般以base64的编码进行传输,这个方法把它解析成字符串。



其他处理程序:

CGI处理程序所需配置
SetHandler mod_python
PythonHandler mod_python.cgihandler

apache配置支持PSP
AddHandler mod_python .psp
PythonHandler mod_python.psp



6.psp处理程序

html和python代码的混合使用
psp处理程序用<%%>包括

[root@www psp]# vi index.psp
<%
from random import choice
adjectives = [‘beatiful‘,‘cruel‘]
%>
<html>
   <head>
     <title>hello</title>
   </head>
        <body>
        <p>hello.<%=choice(adjectives)%> girl. my name is ***</p>
        </body>
</html>
A <%
for i in range(3):
  %>
  merry.
<%
%>

merry christamas time. 

结果显示:

hello.beatiful girl. my name is ***

A merry. merry. merry. merry christamas time.


<% %>空的用来终止该for块,不然下面的信息也会输出三次