标准CGI: 23 次请求/秒
mod_python CGI处理器: 385 次请求/秒
mod_python 发布处理器: 476 次请求/秒
mod_python 处理器: 1203 次请求/秒
[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
如果在编译的过程中出现了如下错误:
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)”
/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>
#!/usr/bin/python
from mod_python import apache
def handler(req):
req.content_type=‘text/plain‘
req.write("Hello, world!")
[root@www pyweb]#
解释一下这个程序:
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
于是觉得是config文件中 PythonHandler index的影响,去掉该行之后无法解析了。
AddHandler mod_python .py
PythonHandler index
PythonDebug On
发布器(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 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>
#-*- 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
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 -*-
重新保存即可
假设我们想用密码保护一个目录,用名字:spam,密码:eggs来登陆。
首先,我们需要告诉apache当需要认证的时候去调用我们的认证处理器。我们通过在配置文件中加入pythonAuthenHandler来实现,如下:
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
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]#
pw = req.get_basic_auth_pw()
我们通过这一句代码得到密码。http在传输验证密码的时候一般以base64的编码进行传输,这个方法把它解析成字符串。
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.标准CGI: 23 次请求/秒
mod_python CGI处理器: 385 次请求/秒
mod_python 发布处理器: 476 次请求/秒
mod_python 处理器: 1203 次请求/秒
[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
如果在编译的过程中出现了如下错误:
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)”
/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>
#!/usr/bin/python
from mod_python import apache
def handler(req):
req.content_type=‘text/plain‘
req.write("Hello, world!")
[root@www pyweb]#
解释一下这个程序:
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
于是觉得是config文件中 PythonHandler index的影响,去掉该行之后无法解析了。
AddHandler mod_python .py
PythonHandler index
PythonDebug On
发布器(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 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>
#-*- 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
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 -*-
重新保存即可
假设我们想用密码保护一个目录,用名字:spam,密码:eggs来登陆。
首先,我们需要告诉apache当需要认证的时候去调用我们的认证处理器。我们通过在配置文件中加入pythonAuthenHandler来实现,如下:
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
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]#
pw = req.get_basic_auth_pw()
我们通过这一句代码得到密码。http在传输验证密码的时候一般以base64的编码进行传输,这个方法把它解析成字符串。
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.