含有章节索引的中文 文章模板

-- oatil, eddyxu [DateTime(2004-08-09T23:22:00Z)] TableOfContents

mod_python中文文档

mod_python是apache组织的一个项目,通过它,可以开发psp或cgi,mod_python功能强大,速度快,是非常优秀的web开发工具。

第一章 简介

1.1 性能

mod_python的一个最主要优点就是在性能上超越传统CGI。下面是一个非常粗略的测试。该测试是在一台运行Red Hat Linux 7.3的奔腾1.2G的机器上完成的。Ab 用来对4种脚本进行测试,所有的都是从标准cgi模块输入(因为这是一个典型Python cgi脚本开始的方式), 然后输出一个简单的单词"Hello!"。这个结果是基于10000次并发为1的请求。

     Standard CGI:               23 requests/s
    Mod_python cgihandler:     385 requests/s
    Mod_python publisher:      476 requests/s
    Mod_python handler:       1203 requests/s

1.2 适应性

Apache分阶段的处理请求(比方说:读取请求,解析header, 检查存取路径,等等)。这些阶段能被称为"处理器"(handler)的函数实现。传统上, "处理器"是由C语言编写,并编译成Apache的模块。Mod_python提供了一个通过Python写的Apache处理器的来扩展Apache功能的方法。关于Apache请求处理过程的详尽描述,请参阅 [http://dev.apache.org/API.html Apache API Notes], 也可以参阅 [http://www.modpython.org/python10/ Mod_python - Integrating Python with Apache]。

为了轻松地从CGI移植,一个标准的mod_python处理器提供了模拟的CGI环境,允许用户在不对代码做任何修改的情况下,使遗留的脚本运行在mod_python下(大多数情况)。

{{{See Also:

http://dev.apache.org/ Apache Developer Resources http://www.modpython.org/python10/ Mod_Python - Integrating Python with Apache, presented at Python 10

}}}

1.3 历史

Mod_python起源于一个被称为Httpdapy(1997)的项目。很长时间以来, Httpdapy并没有被称作mod_python,因为Httpdapy不是专门用于Apache的。 Httpdapy被设计成跨平台的,实际上最初是为Netscape server写的(那个时候被称为Nsapy)(1997)

这个Httpdapy的README文件的摘要,很好的阐述了在HTTP server中嵌入Python所带来的挑战和解决方案。

第二章 安装

翻译中

第三章 指南

现在通过前一章的学习,我们已经学会并安装好mod_python,现在可以通过快速阅读本章进入程序开发阶段。 我强烈推荐你在阅读完本章以后接着阅读(至少是前面的部分)第4章python API的内容。

3.1 快速开始,学习发布处理器(Publisher Handler)

这一节为我们提供了一个快速的关于发布处理器的概况,从而使我们可以不用关注太多的细节就可以写出程序。在这本指南的最后一节,会有一个更详细全面的关于mod_python处理器如何工作的讲解。

发布处理器是mod_python的众多标准处理器中的一个,为了使你的发布处理器能够正常工作,需要在你的配置文件(通常是httpd.conf)中加入下面几句话:

<Directory D:/apache/Apache2/cgi-bin/oa>
        AddHandler mod_python .py
        PythonHandler mod_python.publisher
        PythonDebug On
</Directory>

(注意:D:/apache/Apache2/cgi-bin/oa是我的机器上的路径)

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

下面是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>

注意<form>标签的action指向form.py/email。接下来我们编写这个名叫form.py的脚本,如下:

import smtplib
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

当用户点击确定按钮的时候,发布处理器就会调用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()直接读写客户端等等。

阅读6.1节可以获得更多关于发布处理器的信息.

3.2 快速学习,看一下apache怎样处理请求

如果你想更深入的研究mod_python的功能,你需要弄明白一个处理器到底是什么。

apache是分步骤处理请求的,例如,第一步可能是确定用户,接下来验证用户是不是允许访问特定的文件,然后读这个文件并把它发送到客户端。一个典型的静态文件请求包括三步:(1)解析请求的URI为文件在服务器上的路径。(2)读文件并把它发送到客户端。(3)记录请求日志。这个日志中记录了执行的步骤,记录内容的多少取决于配置文件中的设置。

一个处理器就是处理其中某一步的方法,有可能在处理某一步的时候需要用到不止一个处理器,在这种情况下,这几个处理器将被apache依次调用。每一步都会有一个默认的apache处理器(大多数情况下都是很基础的方法或者不做任何事情)。与此同时,apache模块还提供了附加的处理器,比如mod_python.

mod_python为apache提供了几乎所有需要用到的处理器,mod_python的处理器默认的不会提供任何方法,除非我们明确的在配置文件中指示。这些指示以"python"开始,以"Handler"结束(比如: pythonAuthenHandler )它对应于一个python方法,这个方法处理众多步骤中的一步。所以mod_python的方法扮演的是发报机(dispatcher)的角色,通过它联系apache处理器和开发人员(比如你)写的python方法。

最经常用到的处理器是 pythonHandler,它处理那些请求提供内容的步骤。因为它没有名字,所以有时候它被作为泛指的处理器。这个处理器的默认的apache动作是读文件并把它发送的客户端。你写的大多数程序都会重载这个处理器。 如果想了解所有的处理器,请查看第5章 apache指示

3.3 那么mod_python到底做了些什么呢?

假设我们有下面的配置文件:

    <Directory /mywebdir>
       AddHandler mod_python .py
       PythonHandler myscript
       PythonDebug On
    </Directory>

注意: /mywebdir 是一个物理绝对路径。 还有一个python程序‘/mywedir/myscript.py’如下:

from mod_python import apache
def handler(req):
   req.content_type = "text/plain"
   req.write("Hello World!")
   return apache.OK

这里是说明 addHandler 指示告诉 apache 所有在mywebdir目录或者子目录下的关于py文件的请求都需要被mod_python 执行, pythonHandler myscript 指示告诉 mod_python 用 myscript 执行处理器.

“pythonDebug On” 指示告诉mod_python如果python发生错误,就把错误信息打印到客户端 (相对于写入日志文件),在开发的时候这个选项非常有用。 当一个请求发出时,apache开始分步通过它的请求处理步骤调用mod_python中的处理器.Mod_python的处理器检查请求的那个处理器是否在配置文件中指定了(记住,它的角色是发报机),在我们的例子中,mod_python不会为所有的处理器所任何动作,除了默认的处理器,当我们请求默认处理器的时候,mod_python会发现”pythonHandler myscript”指示,并按照下面的步骤来进行:

1.如果以前没有做过,那么就按照pythonHandler的指示在sys.path中寻找。

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

3.在myscript中寻找控制器请求的方法。

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对象传递,请注意,没有response对象。

req.content_type = "text/plain" 

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

req.write("Hello World!") 

这条语句把字符串” Hello World!”写到客户端。

return apache.OK 

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

一些提示:如果你仔细阅读的话,就会发现上面的代码没有指定处理器代码执行的顺序,唯一必须的条件就是它是一个.py文件。实际上文件的名字并不重要,即使URL中指向的文件并不存在,所以,对于上面的配置,http://myserver/mywebdir/myscript.pyhttp://myserver/mywebdir/montypython.py 执行的结果是一样的。

3.4 现在学习一些更复杂的---认证

现在你已经知道了该怎样写一个简单的处理器,让我们来尝试着写一些更复杂的东西。 假设我们想用密码保护一个目录,我们想用spam密码是eggs来登陆。 首先,我们需要告诉apache当需要认证的时候去调用我们的认证处理器。 我们通过在配置文件中加入pythonAuthenHandler来实现,如下:

    <Directory /mywebdir>
       AddHandler mod_python .py
       PythonHandler myscript
       PythonAuthenHandler myscript
       PythonDebug On
    </Directory>

注意,我们在这里为两个不同的处理器指定了相同的脚本,这是可以的,如果你还记得,mod_python会在同一个脚本中为不同的处理器查找不同的方法,接下来,我们需要告诉apache我们使用的是最基本的HTTP认证,我们的配置文件应该象下面这样:

    <Directory /mywebdir>
      AddHandler mod_python .py
      PythonHandler myscript
      PythonAuthenHandler myscript
      PythonDebug On
      AuthType Basic
      AuthName "Restricted Area"
      require valid-user
   </Directory>

现在我们要在myscript.py中写一个认证处理器方法,一个基本的认证处理器象下面这样:

from mod_python import apache
def authenhandler(req):
    pw = req.get_basic_auth_pw()
    user = req.user
    if user == "spam" and pw == "eggs":
        return apache.OK
    else:
        return apache.HTTP_UNAUTHORIZED

让我们一行一行的看这段代码:

def authenhandler(req):

第四章 Python API

翻译中

第五章 Apache配置文件指示

翻译中

第六章 标准处理器

翻译中