19.1、Python CGI编程
CGI是Common Gateway Interface的缩写,表示通用网关接口。CGI是一段运行在服务器上的程序,例如运行在HTTP服务器上提供同客户端HTML页面的接口。本节将详细讲解使用Python程序开发CGI程序的知识。
19.1.1、CGI介绍
CGI是WWW技术中最重要的技术之一,有着不可替代的重要地位。CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。
处理过程的第一步是Web服务器从客户端接到了请求(即GET或者POST),并调用相应的应用程序。然后它等待HTML页面,与此同时,客户端也在等待。一旦应用程序处理完成,它会将生成的动态HTML页面返回服务器端。接下来,服务器端再将这个最终结果返回给用户。对于表单处理过程,服务器与外部应用程序交互,收到并将生成的HTML页面通过CGI返回客户端。
由此可见,CGI 在Web 服务器和应用之间充当了交互作用,这样才能够处理用户表单,生成并返回最终的动态HTML页。
19.1.2、搭建CGI服务器
要想使用Python语言进行CGI 开发,首先需要安装一个Web服务器,并将其配置成可以处理Python CGI 请求,然后让Web服务器访问CGI脚本。当然,其中有些操作也许需要获得系统管理员的帮助。下面将介绍在Windows系统中搭建CGI服务器的过程。
在IDLE编辑器中,输入如下命令可以获取Python自带服务器的地址。
from http.server import CGIHTTPRequestHandler,test;test(CGIHTTPRequestHandler)
在CMD控制台界面中,通过输入Python命令也可以获取Python自带服务器的地址,例如在机器中输入如下命令。
python C:\Users\apple0\AppData\Local\Programs\Python\Python36\Lib\http\server.py
此时会在控制台中显示Python自带服务器的地址,如图19-1所示。
建议安装一个真正的Web服务器,现实中可以下载并安装的服务器有Apache、ligHTTPD或thttpd。其中在Apache中有许多插件或模块可以处理Python CGI,使用Apache服务器访问CGI的流程如下所示。
(1)自行安装好Apache(httpd)环境,确保Apache在系统中已经能成功运行并可以访问。
(2)打开Apache的配置文件conf/httpd.conf,找到下面的内容。
ScriptAlias /cgi-bin/ "/Apache22/cgi-bin/" |
上述内容指定了当访问http://yourdomain/cgi-bin/时应该映射到文件系统中的哪个目录,例如可以修改成以下内容。
ScriptAlias /cgi-bin/ "d:/programs/Apache22/cgi-bin/" |
(3)找到下面的内容。
<Directory "/Apache22/cgi-bin"> AllowOverride None Options None Order allow,deny Allow from all </Directory> |
在此处同样把目录修改为文件系统中真实的路径,例如以下路径。
<Directory "d:/servers/Apache22/cgi-bin">
(4)找到下面的内容。
AddHandler cgi-script .cgi
去掉此行的"#"注释(如果有),在后面可以追加后缀".py",这是可选的。如果不加,也可以使用".cgi"后缀。
(5)到此为止,Apache服务器配置完成。接下来,可以编写Python脚本文件,编辑完成后放到Apache目录下的"cgi-bin"目录中即可运行。
19.1.3、第一个CGI程序
在下面的实例代码中,使用Python语言编写了第一个CGI程序,文件名为hello.py,文件位于"www/cgi-bin"目录中。
实例19-1 创建可靠的、相互通信的"客户端/服务器"
源码路径 daima\19\19-1
实例文件hello.py的具体实现代码如下所示。
print ("Content-type:text/html") #打印网页头 print () # 空行,告诉服务器结束头部 print ('<html>') #HTML标签 print ('<head>') #HEAD标签 print ('<meta charset="utf-8">') #META标签 print ('<title>Hello Word - 我的第一个 CGI 程序! </title>') print ('</head>') #HEAD标签 print ('<body>') #body标签 print ('<h2>Hello Word! 我是来自菜鸟教程的第一个CGI 程序</h2>') print ('</body>') #body标签 print ('</html>') #HTML标签 |
将上述实例代码文件另存为文件hello.py,然后通过如下命令修改文件权限为755。
chmod 755 hello.py |
在浏览器中访问之后的执行效果如图19-2所示。
19.2、使用Tornado框架
Tornado是FriendFeed使用的可扩展的非阻塞式Web服务器及其相关工具的开源版本。这个Web框架看起来有些像web.py或者Google的webapp。不过,为了能有效利用非阻塞式服务器环境,这个Web框架还包含了一些有用的工具和优化措施。本节将详细讲解在Python程序中使用Tornado框架的知识。
19.2.1、Tornado框架介绍
Tornado是一种目前比较流行的、强大的、可扩展的Python的Web非阻塞式开源服务器框架,也是一个异步的网络库,能够帮助开发者快速简单地编写出高速运行的Web应用程序。
Tornado基于Bret Taylor和其他人员为FriendFeed所开发的网络服务框架,当FriendFeed被Facebook收购后得以开源。Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API)进行异步交互的工具。
自从2009年第一个版本发布以来,Tornado已经获得了很多社区的支持,并且在一系列不同的场合得到应用。除了FriendFeed和Facebook外,还有很多公司在生产上转向Tornado,其中包括Quora、Turntable.fm、Bit.ly、Hipmunk以及MyYearbook等。
Tornado框架的主要特点如下所示。
"非阻塞式服务器。
"运行速度快。
"并发打开数千个连接。
"支持WebSocket连接。
在现实应用中,通常将Tornado库分为如下所示的4部分。
"tornado.Web:创建Web应用程序的Web框架。
"HTTPServer和AsyncHTTPClient:HTTP服务器与异步客户端。
"IOLoop和IOStream:异步网络功能库。
"tornado.gen:协程库。
19.2.2、Python和Tornado框架
在Python程序中使用Tornado框架之前,首先需要搭建Tornado框架环境。可以通过pip或者easy_install命令进行安装。其中"pip"安装命令如下所示。
pip install tornado |
"easy_install"安装命令如下所示。
easy_install tornado |
在控制台界面使用"easy_install"命令的安装界面如图19-3所示。
在Tornado框架中,是通过继承类tornado.Web.RequestHandler来编写Web服务器端程序的,并编写get()、post()业务方法,以实现对客户端指定URL的GET请求和POST请求的回应。然后启动框架中提供的服务器以等待客户端连接,处理相关数据并返回请求信息。
下面的实例代码演示了使用Python语言编写一个基本Tornado框架程序的过程。
实例19-2 编写一个基本Tornado框架程序
源码路径 daima\19\19-2
实例文件app.py的具体实现代码如下所示。
import tornado.ioloop #导入Tornado框架中的相关模块 import tornado.web #导入Tornado框架中的相关模块 #定义子类MainHandler class MainHandler(tornado.web.RequestHandler): def get(self): #定义请求业务函数get() self.write("Hello, world") #显示文本 def make_app(): #定义应用配置函数 return tornado.web.Application([ (r"/", MainHandler), #定义URL映射列表 ]) if __name__ == "__main__": app = make_app() #调用配置函数 app.listen(8888) #设置监听服务器8888端口 tornado.ioloop.IOLoop.current().start() #启动服务器 |
在上述实例代码中,首先导入Tornado框架的相关模块,然后自定义URL的响应业务方法(GET、POST等)。接下来,实例化Tornado模块中提供的Application类,并传URL映射列表及有关参数,最后启动服务器即可。在命令提示符下的对应子目录中执行以下命令。
python app.py |
如果没有语法错误,服务器就已经启动并等待客户端连接了。在服务器运行以后,在浏览器地址栏中输入http://localhost:8888,就可以访问服务器,并看到默认主页页面。在浏览器中的执行效果如图19-4所示。
通过上述实例可以看出,使用Tornado框架编写服务器端程序的代码结构是非常清晰的。其基本工作就是编写相关的业务处理类,并将它们映射到某一特定的URL,Tornado框架服务器收到对应的请求后进行调用。一般来说,如果是比较简单的网站项目,可以把所有的代码放入同一个模块之中。但为了维护方便,可以按照功能将其划分到不同的模块中,其一般模块结构(目录结构)如下所示。
proj\
manage.py #服务器启动入口
settings.py #服务器配置文件
url.py #服务器URL配置文件
handler\
login.py #相关URL业务请求处理类
db\ #数据库操作模块目录
static\ #静态文件存放目录
js\ #JS文件存放目录
css\ #CSS样式表文件目录
img\ #图片资源文件目录
templates\ #网页模板文件目录
19.2.3、获取请求参数
在Python程序中,客户端经常需要获取如下3类参数。
"URL中的参数。
"GET中的参数。
"POST中的参数。
(1)获取URL中的参数。
在Tornado框架中,要想获取URL中包含的参数,需要在URL定义中定义获取参数,并在对应的业务方法中给出相应的参数名进行获取。在Tornado框架的URL定义字符串中,使用正则表达式来匹配URL及URL中的参数,比如以下代码。
(r"uid/([0-9]+)",UserHdl) |
上述形式的URL字符串定义可以接受形如"uid/"后跟一位或多位数字的客户端URL请求。针对上面的URL定义,可以以如下方式定义get()方法。
def get (self,uid): pass |
此时,当发来匹配的URL请求时,会截取与正则表达式匹配的部分,传递给get()方法,这样可以把数据传递给uid变量,以在方法get()中得到使用。
下面的实例代码演示了在GET方法中获取URL中参数的过程。
实例19-3 在GET方法中获取URL中参数
源码路径 daima\19\19-3
实例文件can.py的具体实现代码如下所示。
import tornado.ioloop #导入Tornado框架中的相关模块 import tornado.web #导入Tornado框架中的相关模块 class zi(tornado.web.RequestHandler): #定义子类zi def get(self,uid): #获取URL参数 self.write('你好,你的UID号是:%s!' % uid) #显示UID,来源于下面的正则表达式 app = tornado.web.Application([ #使用正则表达式获取参数 (r'/([0-9]+)',zi), ],debug=True) if __name__ == '__main__': app.listen(8888) #设置监听服务器8888端口 tornado.ioloop.IOLoop.instance().start() #启动服务器 |
在上述实例代码中,使用正则表达式定义了URL字符串,使用get()方法获取了URL参数中的uid。在浏览器中的执行效果如图19-5所示。
(2)获取GET和POST中的参数。
在Tornado框架中,要想获取GET或POST中的请求参数,只需要调用从类RequestHandler中继承来的 get_ argument()方法即可。方法get_argument()的语法格式如下所示。
get_argument('name', default='',strip=False)
"name:请求中的参数名称。
"default:当没有获取参数时指定一个默认值。
"strip:指定是否对获取的参数进行两头去空格处理。
下面的实例代码演示了获取POST中参数的过程。
实例19-4 获取POST中的参数
源码路径 daima\19\19-4
实例文件po.py的具体实现代码如下所示。
import tornado.ioloop #导入Tornado框架中的相关模块 import tornado.web #导入Tornado框架中的相关模块 html_txt = """ #变量html_txt初始化赋值 <!DOCTYPE html> #下面是一段普通的HTML代码 <html> <body> <h2>收到GET请求</h2> <form method='post'> <input type='text' name='name' placeholder= '请输入你的姓名' /> <input type='submit' value='发送POST请求' /> </form> </body> </html> """ class zi(tornado.web.RequestHandler): #定义子类zi def get(self): #定义方法get()处理get请求 self.write(html_txt) #处理为页面内容 def post(self): #定义方法post()处理post请求 name = self.get_argument('name',default='匿名',strip=True) #获取上面表单中的姓名name self.write("你的姓名是:%s" % name) #显示姓名 app = tornado.web.Application([ #实例化Application对象 (r'/get',zi), ],debug=True) if __name__ == '__main__': app.listen(8888) #设置监听服务器8888端口 tornado.ioloop.IOLoop.instance().start() #启动服务器 |
在上述实例代码中,当服务器收到GET请求时,返回一个带有表单的页面内容。当用户填写自己的姓名并单击"发送POST请求"按钮时,将用户输入的姓名以POST参数形式发送到服务器端。最后在服务器端调用方法get_argument()来获取输出请求。在浏览器中输入"http://localhost:8888/get"后的执行效果如图19-6所示。
在表单中输入姓名"浪潮软件",然后单击"发送POST请求"按钮后的执行效果如图 19-7所示。
相关阅读:
版权声明:51Testing软件测试网获人民邮电出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。