Python Web 编程:CGI 和WSGI(帮助Web 服务器处理客户端数据)
简介
本章是Web 编程方面的入门章节,将对Python 网络编程做快速而广泛的概述,从Web
浏览到创建用户反馈表单,从识别URL 到生成动态Web 页面。本章首先介绍通用网关接口
(Common Gateway Interface CGI),接着讨论Web 服务器网关接口(Web Server Gateway
Interface, WSGI)
帮助Web 服务器处理客户端数据
本节将介绍CGI,包括CGI 的含义、出现原因,以及与Web 服务器的工作方式,接着介
绍如何使用Python 创建CGI 应用。
CGI 简介
Web 最初目的是在全球范围内对文档进行在线存储和归档(大多用于教学和科研)。这
些文件通常用静态文本表示,一般是HTML。
HTML 是一个文本排版工具,而不像是一种语言,可用于指明字体的类型、大小、样式。
HTML 的主要特性是其超文本的兼容性,如突出显示标明一些文本,或用图形元素作为链接,
指向其他本地文档或位于网上其他地方的文档。这样就可以通过鼠标单击或者其他用户选择机制
来访问相关文档。这些静态HTML 文档位于Web 服务器上,在需要的时候会被发送到客户端。
随着因特网和Web 服务的发展,除了浏览之外,还需要处理用户的输入。如在线零售商
需要处理单个订单,网上银行和搜索引擎需要为每个用户建立独立账号。因此出现了表单,
它们成为Web 站点从用户获得特定信息的唯一形式(在Java applet 出现之前)。反过来,在
客户提交了特定数据后,就要求立即生成HTML 页面。
现在Web 服务器仅有一点做得很不错,即了解用户需要哪个文件,接着将这个文件(即
HTML 文件)发送给客户端。Web 服务器不能处理表单中传递过来的用户相关的数据。这不
是Web 服务器的职责,Web 服务器将这些请求发送给外部应用,将这些外部应用动态生成的
HTML 页面发送回客户端。
处理过程的第一步是Web 服务器从客户端接到了请求(即GET 或者POST),并调用相
应的应用程序。它然后等待HTML 页面,与此同时,客户端也在等待。一旦应用程序处理完
成,它会将生成的动态HTML 页面返回服务器端,然后服务器端再将这个最终结果返回给用
户。对于表单处理过程,服务器与外部应用程序交互,收到并将生成的HTML 页面通过CGI
返回客户端。
客户端输入给Web 服务器端的表单可能包括处理过程和一些存储在后台数据库中的表
单。需要记住的是,含有需要用户输入项(如文本框、单选按钮等)、Submit 按钮、图片的
Web 页面,都会涉及某种CGI 活动。
创建HTML 的CGI 应用程序通常是用高级编程语言来实现的,可以接受、处理用户数
据,向服务器端返回HTML 页面。在接触CGI 之前,需要告诫的是,一般生产环境的Web
应用都不再使用CGI 了。
由于CGI 有明显的局限性,以及限制Web 服务器同时处理客户端的数量,因此CGI 被
抛弃了。一些关键的Web 服务使用C/C++这样的编译语言进行扩展。如今Web 服务器典型
的部件有Apache 和集成的数据库访问部件(MySQL 或者PostgreSQL)、Java(Tomcat)、PHP
和各种动态语言(如Python 或Ruby)模块,以及SSL/security。然而,如果在小型的私人
Web 网站或者小组织的Web 网站上工作,就没有必要使用这些用于关键任务的强大而复杂的
Web 服务器。在开发小型Web 网站或为了测试时,可以使用CGI。
另外,现在出现了很多Web 应用程序开发框架和内容管理系统,这些工具淘汰了CGI。
然而,这些新工具虽然进行了浓缩和抽象,但仍旧遵循着CGI 最初提供的模式,如获取用户
输入的信息,根据输入执行相关代码,并提供一个有效的HTML 作为最终输出传递给客户端。
因此,为了开发出高效的Web 服务有必要学习CGI,了解其中的基础。
下一节将会介绍使用cgi 模块在Python 中建立一个CGI 应用程序。
CGI 应用程序
CGI 应用程序和典型的应用程序有些不同,主要的区别在于输入、输出以及用户和程
序交互方面。当一个CGI 脚本启动后,需要获得用户提供的表单数据,但这些数据必须要
从Web 客户端才可以获得,而不是从服务器或者硬盘上获得。这就是大家熟知的请求
(request)。
与标准输出不同,这些输出将会发送回连接的Web 客户端,而不是发送到屏幕、GUI
窗口或者硬盘上。这些返回的数据必须是具有一系列有效头文件的HTML 标签数据。如果
Web 客户端是浏览器,由于浏览器只能识别有效的HTTP 数据(也就是MIME 头和HTML),
所以会发生错误(具体一点,就是内部服务器错误)。
cgi 模块
cgi 模块中有个主要类:FieldStorage 类,其完成了所有的工作。Python CGI 脚本启动时
会实例化这个类,通过Web 服务器从Web 客户端读出相关的用户信息。在实例化完成后,
其中会包含一个类似字典的对象,它具有一系列的键值对。键就是通过表单传入的表单条目
的名字,而值则包含相应的数据。
这些值可以是以下三种对象之一。一是FieldStorage 对象(实例)。二是另一个名为
MiniFieldStorage 类的类似实例,用在没有文件上传或mulitple-part 格式数据的情况下。
MiniFieldStorage 实例只包含名程和数据的键值对。最后,它们还可以是这些对象的列表。当
表单中的某个字段有多个输入值时就会产生这种对象。
对于简单的Web 表单,可以发现其中所有的MiniFieldStorage 实例。下边所有的例子都
仅针对这种普通情况。
cgitb 模块
前面已经提到,返回Web 服务器的合法响应(将会转发给用户/浏览器)必须含有合法
的HTTP 头和HTML 标记过的数据。是否考虑过在CGI 应用崩溃时如何返回数据呢?想一
想如果是一个Python 脚本发生错误呢?对,会出现回溯消息。那么回溯的文本消息是否会被
认为是合法的HTML 头或HTML?不会。
Web 服务器在收到无法理解的响应时,会抛弃这个响应,返回“500 错误”。500 是一个
HTTP 响应编码,它表示发生了一个内部服务器错误。一般是服务器所执行的应用程序发生
了错误。此时在浏览器中给出的提示消息没什么用,要么是空白,要么显示“内部服务器错
误”或类似消息。
当Python 程序在命令行或集成开发环境(IDE)中运行时,发生的错误会生成回溯消息,
指出错误发生的位置,在浏览器中不会显示回溯消息。若想在浏览器中看到的是Web 应用程
序的回溯信息,而不是“内部服务器错误”,可以使用cgitb 模块。
为了启用转储回溯消息,所要做的就是将下面的代码插入CGI 应用中并进行调用。









