两、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.安装


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


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假设错误发生。就把错误打印信息到client (相对于写入日志文件),在开发的时候这个选项很实用。

当一个请求发出时,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对象提供了全部可能用到的信息。比方client的IP,头,URI等等.返回client的信息仍然通过request对象传递。注意,在mod_python中没有response对象。

req.content_type = "text/plain" 

这条语句设置文档类型为” text/plain”。默认的一般是” text/html”,可是由于我们的处理器不处理不论什么html, 所以“text/plain”更合适一些。

req.write("Hello World!") 

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

return apache.OK 

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

一些提示:假设你细致阅读的话,就会发现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 Webserver中嵌入了具有所有功能的Python解释器。这个模块通常被用来强劲而高效地产生动态网页,当然它另一些其它的用途。

编写mod_python程序在非常多方面和编写CGI程序类似。所以熟悉CGI(详见第18章)会对您学习mod_python有非常大的帮助。

mod_python和CGI之间也有不同的地方。在本章中。我们也将介绍这些不同。 19.1  理解为什么须要mod_python 我们已经在第18章中讨论过,CGI脚本是最经常使用的一种产生动态网页的方法。每当有页面请求的时候,相应的CGI脚本就被调用。它读取请求,产生应答,并终于终止。这是仿效HTTP的操作,后者的核心是一次为一个单一的请求服务。

下一次又有请求的时候。CGI脚本会被又一次调用。这种设计就使CGI脚本具有语言和server中立的特性;并且其实,全部流行的Webserver和程序语言都支持CGI。

然而,这样的兼容性是有代价的:那就是性能。

启动一个CGI脚本非常慢,操作系统须要为它建立新进程。Python解释器须要初始化和加载脚本。对于连接数据库的CGI脚本来说,性能就更差了,由于每次显示一个页面的时候,它们都必须建立一个新的数据库session。正是由于这个原因。CGI脚本不适合那些流量大的网站。 mod_python就是一个解决问题的方法。它实际上在Apache Webserver中嵌入了一个完整的Python解释器。

CGI脚本仅仅在server进程初始化的时候加载一次。

数据库连接也能够在Webserver初始化的时候建立,并保持连接直到Webserver关闭。每当要产生一个页面的时候,一个特殊的函数就被调用,全部关于请求的数据都被传入该函数。

这个函数有权訪问Webserver初始化时建立的环境变量。比如,它能够反复使用已经存在的数据库连接。
虽然这样的方法必须使用Apacheserver,可是它的长处要比缺点多得多,尤其是当您从头開始设计一个完整的Web应用的时候。

Python能够作为那些专门开发Web应用语言的替代者。比如PHP。 其实,mod_python除了用在提供页面之外还能够做其它的事情。它还能够在多个方面和Apache系统结合。比如:Apache提供了多种认证的处理方法。这些方法能够使您依据一个包括username和password的文本文件或LDAP数据库来认证用户。

您能够使用mod_python来编写您自己的认证处理程序(也许它通过一个远程XML-RPCserver来验证),并随时在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">

          username: <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



当用户点击确定button的时候。公布处理器就会调用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()直接读写client等等。






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

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

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

又一次保存就可以



5.认证

如果我们想用password保护一个文件夹,用名字:spam,password: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   #加上该句则输入username和password之后报错无法找到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()

我们通过这一句代码得到password。http在传输验证password的时候一般以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.安装


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


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假设错误发生。就把错误打印信息到client (相对于写入日志文件),在开发的时候这个选项很实用。

当一个请求发出时,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对象提供了全部可能用到的信息,比方client的IP,头,URI等等.返回client的信息仍然通过request对象传递,注意。在mod_python中没有response对象。

req.content_type = "text/plain" 

这条语句设置文档类型为” text/plain”。

默认的一般是” text/html”,可是由于我们的处理器不处理不论什么html, 所以“text/plain”更合适一些。

req.write("Hello World!") 

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

return apache.OK 

这条语句告诉apache一切正常,并且请求也已经被处理了。

假设出现异常,这一行应该返回apache.HTTP INTERNAL SERVER ERROR或返回apache.HTTP FORBIDDEN。并且apache会在日志中记录这个错误,并产生一条错误信息给client。

一些提示:假设你细致阅读的话。就会发现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 Webserver中嵌入了具有所有功能的Python解释器。这个模块通常被用来强劲而高效地产生动态网页。当然它另一些其它的用途。
编写mod_python程序在非常多方面和编写CGI程序类似。所以熟悉CGI(详见第18章)会对您学习mod_python有非常大的帮助。mod_python和CGI之间也有不同的地方,在本章中,我们也将介绍这些不同。 19.1  理解为什么须要mod_python 我们已经在第18章中讨论过。CGI脚本是最经常使用的一种产生动态网页的方法。每当有页面请求的时候,相应的CGI脚本就被调用。

它读取请求,产生应答,并终于终止。这是仿效HTTP的操作,后者的核心是一次为一个单一的请求服务。下一次又有请求的时候,CGI脚本会被又一次调用。这种设计就使CGI脚本具有语言和server中立的特性;并且其实,全部流行的Webserver和程序语言都支持CGI。

然而。这样的兼容性是有代价的:那就是性能。启动一个CGI脚本非常慢,操作系统须要为它建立新进程。Python解释器须要初始化和加载脚本。对于连接数据库的CGI脚本来说。性能就更差了,由于每次显示一个页面的时候,它们都必须建立一个新的数据库session。正是由于这个原因,CGI脚本不适合那些流量大的网站。 mod_python就是一个解决问题的方法。它实际上在Apache Webserver中嵌入了一个完整的Python解释器。CGI脚本仅仅在server进程初始化的时候加载一次。数据库连接也能够在Webserver初始化的时候建立,并保持连接直到Webserver关闭。

每当要产生一个页面的时候。一个特殊的函数就被调用,全部关于请求的数据都被传入该函数。这个函数有权訪问Webserver初始化时建立的环境变量。比如。它能够反复使用已经存在的数据库连接。
虽然这样的方法必须使用Apacheserver,可是它的长处要比缺点多得多,尤其是当您从头開始设计一个完整的Web应用的时候。Python能够作为那些专门开发Web应用语言的替代者。比如PHP。 其实,mod_python除了用在提供页面之外还能够做其它的事情。

它还能够在多个方面和Apache系统结合。比如:Apache提供了多种认证的处理方法。这些方法能够使您依据一个包括username和password的文本文件或LDAP数据库来认证用户。

您能够使用mod_python来编写您自己的认证处理程序(也许它通过一个远程XML-RPCserver来验证),并随时在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">

          username: <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



当用户点击确定button的时候。公布处理器就会调用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()直接读写client等等。






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

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

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

又一次保存就可以



5.认证

如果我们想用password保护一个文件夹,用名字:spam,password: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   #加上该句则输入username和password之后报错无法找到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()

我们通过这一句代码得到password。

http在传输验证password的时候一般以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. python-web apache mod_python 模块的安装

    安装apache 下载mod_python 编译安装 测试 下载mod_python,下载地址:mod_python 在GitHub 上面, 下载之后:目录结构如下: 安装依赖: #查找可安装的依赖 ...

  2. python安装、模块安装

    python安装 windows 下载安装包 https://www.python.org/downloads 改环境变量 [右键计算机]-->[属性]-->[高级系统设置]-->[ ...

  3. python3 中mlpy模块安装 出现 failed with error code 1的决绝办法(其他模块也可用本方法)

    在python3 中安装其它模块时经常出现 failed with error code 1等状况,使的安装无法进行.而解决这个问题又非常麻烦. 接下来以mlpy为例,介绍一种解决此类安装问题的办法. ...

  4. [转] npm 模块安装机制简介

    npm 是 Node 的模块管理器,功能极其强大.它是 Node 获得成功的重要原因之一. 正因为有了npm,我们只要一行命令,就能安装别人写好的模块 . $ npm install 本文介绍 npm ...

  5. npm 模块安装机制简介

    npm 是 Node 的模块管理器,功能极其强大.它是 Node 获得成功的重要原因之一. 正因为有了npm,我们只要一行命令,就能安装别人写好的模块 . $ npm install 本文介绍 npm ...

  6. Mac MySQLdb模块安装,可算解决了

    转载:http://blog.csdn.net/janronehoo/article/details/25207825 短评:这篇文章感觉是比较全面解决Mac MySQLdb模块安装问题的文章了,特别 ...

  7. perl模块安装

    转自: http://www.cnblogs.com/itech/archive/2009/08/10/1542832.html http://www.mike.org.cn/blog/index.p ...

  8. 详解npm的模块安装机制 --社会我npm哥,好用话不多

      依赖树表面的逻辑结构与依赖树真实的物理结构 依赖树表面的逻辑结构与依赖树真实的物理结构并不一定相同! 这里要先提到两个命令:tree -d(linux)和npm ls(npm) 在一个npm项目下 ...

  9. python机器学习模块安装

    环境:RHEL6.5 离线安装 ############################################################################ 一,本地yum ...

随机推荐

  1. Embedded Linux Primer----嵌入式Linux基础教程--前言

    APractical,Real-WorldApproach ChristopherHallinan 计算机无处不在. 事实上,当然了,对于那些大约在过去25年期间没有生活在洞穴中的人来说没有什么惊奇的 ...

  2. Extjs 3.4 和 web SSH(Ajaxterm)-howge-ChinaUnix博客

    Extjs 3.4 和 web SSH(Ajaxterm)-howge-ChinaUnix博客   Extjs 3.4 和 web SSH(Ajaxterm) 2013-04-07 15:20:17 ...

  3. python socket编程实现的简单tcp迭代server

    与c/c++ socket编程对照见http://blog.csdn.net/aspnet_lyc/article/details/38946915 server: import socket POR ...

  4. 网页favicon.ico图标设置(转)

    随便打开一个网页:比如 http://www.baidu.com/ 可以看到在浏览器的标签头上面显示了一个图标,这个图标是:,也就是我们常说的favicon.ico. 由于这篇文章主要讨论favico ...

  5. hdu1712(分组背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1712 分析: 典型的分组背包问题,如果不会的可以看一下背包九讲. 看下背包九讲中的描述: for 所有 ...

  6. Linux for周期运行命令注意事项

    假定for有一些符号循环指令,需要使用()封闭. for i in {1..4}; do (python /data/UGCRobot/manage/Scheduler.py 1.log > / ...

  7. 基于Redis Sentinel的Redis集群(主从Sharding)高可用方案(转)

    本文主要介绍一种通过Jedis&Sentinel实现Redis集群高可用方案,该方案需要使用Jedis2.2.2及以上版本(强制),Redis2.8及以上版本(可选,Sentinel最早出现在 ...

  8. hdu2126(求方案数的01背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126 题意: n个物品,m元钱,每个物品最多买一次,问最多可以买几件物品,并且输出方案数. 分析:一看 ...

  9. UILabel iOS添加文本控件

    UILabel这是iOS控制,这是UIView子类,只有在UIView文字显示功能的基础上加入.UILabel还查看课程和UIView类别似     //1.创建一个视图对象     //2.配置视图 ...

  10. thinkphp中field的用法

    ThinkPHP的连贯操作方法中field方法有很多的使用技巧,field方法主要目的是标识要返回或者操作的字段,下面详细道来. 1.用于查询 在查询操作中field方法是使用最频繁的. $Model ...