Python CGI 编程

2025年3月17日 | 阅读 12 分钟

在 Python CGI 编程中,我们将学习如何在 Web 上运行 Python 脚本;我们将学习如何将 Python 文件作为 CGI 脚本执行,并讨论其 Web 浏览器配置以将 Python 脚本作为 CGI 运行。此外,我们还将学习以下主题:

  • 什么是 CGI?
  • 网页浏览
  • 为 CGI 配置 Apache Web 服务器
  • 使用 cgi 模块
  • CGI 架构图
  • 将第一个 Python 程序作为 CGI 运行
  • 图例和语法
  • Python CGI 脚本的调试
  • CGI 的功能
  • CGI 的优点
  • CGI 的缺点
  • 常见问题及解决方案

什么是 CGI?

CGI 是 “通用网关接口” 的缩写,用于定义 Web 服务器和自定义脚本之间如何交换信息。NCSA 官方管理 CGI 脚本。

通用网关接口是外部网关程序与服务器(如 HTTP 服务器)进行接口的标准。

简单来说,它是一组用于在服务器和客户端应用程序之间建立动态交互的方法。当客户端向 Web 服务器发送请求时,CGI 程序执行该特定请求并将结果发送回 Web 服务器。

用户可以使用 HTML <form><isindex> 元素在 Web 浏览器中提交信息。服务器有一个名为 cgi-bin 的特殊目录,通常在此处存储 cgi 脚本。当客户端发出请求时,服务器会将附加信息添加到请求中。

这些附加信息可以是客户端的主机名、查询字符串、请求的 URL 等等。Web 服务器执行并将输出发送到 Web 浏览器(或其他客户端应用程序)。

有时服务器通过查询字符串传递数据,该查询字符串是 URL 的一部分。查询字符串可能不总是传统的层次路径结构,如下面的链接所示。

Python 提供了 CGI 模块,该模块有助于调试脚本并支持通过 HTML 表单上传文件。

那么问题来了,Python CGI 脚本的输出是什么样的?HTTP 服务器将输出作为两部分返回,两部分之间由一个空行分隔。第一部分包含多个标头,通知客户端接下来是什么类型的数据。

让我们理解在 Python CGI 编程中生成最小标头部分的以下示例。

示例 -

在上面的示例中,第一个语句表示服务器后面是 html 代码;第二个空行表示标头在此处结束。让我们理解在 Python CGI 编程中生成最小标头部分的以下示例。

示例 -

网页浏览

在理解 CGI 概念之前,我们应该了解当我们点击给定链接时网页或 URL 的内部过程。

  • 客户端(Web 浏览器)与 HTTP 服务器通信并请求 URL,即文件名。
  • 如果 Web 浏览器找到请求的文件,则将其发送回客户端(Web 浏览器),否则将错误消息作为错误文件发送给客户端。
  • 在这里,Web 浏览器负责显示接收到的文件或错误消息。

但是,我们可以设置一个 HTTP 服务器,以便当用户在特定字典中发出请求时,它应该发送给客户端;相反,它作为程序执行,并将结果发送回客户端显示。这个过程称为通用网关接口或 CGI,这些程序称为 CGI 脚本。我们可以将 CGI 程序编写为 Python 脚本、PERL 脚本、Shell 脚本CC++ 程序等。

为 CGI 配置 Apache Web 服务器

我们需要配置 Apache Web 服务器才能在服务器上运行 CGI 脚本。

CGI 架构

Python CGI Programming

使用 cgi 模块

Python 提供了 cgi 模块,它包含许多有用的内置函数。我们可以通过导入 cgi 模块来使用它们。

现在,我们可以继续编写脚本。

上述脚本将激发一个异常处理程序,以在 Web 浏览器中显示发生的错误的详细报告。我们也可以使用以下脚本保存报告。

cgi 模块的上述功能在脚本开发过程中非常有用。这些报告有助于我们有效地调试脚本。当我们获得预期的输出时,我们可以将其删除。

以前,我们讨论过用户使用表单保存信息。那么我们如何获取这些信息呢?Python 提供了 FieldStorage 类。如果表单包含非 ASCII 字符,我们可以将编码关键字参数应用于文档。我们将在 HTML 文档的 <HEAD> 部分找到内容 <META> 标签

FieldStorage 类从标准输入或环境中读取表单信息。

FieldStorage 实例与 Python 字典相同。我们可以在 FieldStorage 实例中使用 len() 和所有字典函数。它会忽略空字符串值的字段。我们也可以通过将可选关键字参数 keep_blank_values 设置为 True 来考虑空值。

示例 -

在上面的示例中,我们使用了表单 ["name"],这里的 name 是 key。这用于提取用户输入的值。

我们可以使用 getvalue() 方法直接获取字符串值。此函数还接受一个可选的第二个参数作为默认值。如果键不存在,它将返回默认值。

如果提交的表单数据中有多个同名字段,我们应该使用 form.getlist() 函数。它返回字符串列表。请看下面的代码,我们添加了任意数量的用户名字段,用逗号分隔。

如果字段是上传的文件,则可以通过 value 属性或 getvalue() 方法访问,并以字节为单位读取上传的文件。让我们理解以下用户上传文件时的代码。

示例 -

有时,在读取上传文件内容时(当用户点击取消按钮或返回按钮时),程序可能会被错误中断。FieldStorage 类提供了 done 属性,将其设置为值 -1。

如果以 “旧” 格式提交表单,则项目将是 MiniFieldStorage 类的实例。在此类中,list、file 和 filename 属性始终为 None

通常,表单通过 POST 提交,并包含带有 FieldStorageMiniStorage 项目的查询字符串。

在这里,我们在下表中定义 FieldStorage 属性。

属性描述
名称它表示字段名。
文件名它表示客户端文件名。
文件它是一个文件(类文件)对象,我们可以从中以字节形式读取数据。
它是一个字符串类型的值。用于文件上传,读取文件并返回字节。
类型它用于显示内容类型。
头文件它是一个字典类型对象,包含所有标头。

FieldStorage 实例使用许多内置方法来操作用户数据。以下是一些 FieldStorage 的方法。

FieldStorage 方法

方法描述
getfirst()它返回收到的第一个值。
getlist()它返回收到的值列表。
getvalue()它是字典的 get() 方法。
keys()它是字典的 keys() 方法
make_file()它返回一个可读写的文档。

将第一个 Python 文件作为 CGI 运行

在本节中,我们将讨论如何在服务器上运行 CGI 程序。在此之前,我们必须确保我们的系统具有以下配置-

  • Apache 服务器
  • Python

如果您的系统已经安装了 XAMPP 服务器,则可以跳过此部分。

安装 XAMPP 服务器

XAMPP 代表跨平台、Apache、MySQLPHPPerl,它提供了本地主机服务器来测试或部署网站。通常,它提供两个基本组件用于安装,第一个是 - Apache,它创建本地服务器,以及 MySQL,我们可以将其用作数据库。

按照以下步骤安装 xampp

步骤 - 1: 访问其官方网站 (https://www.apachefriends.org/download.html) 并下载最新版本。

Python CGI Programming

步骤 - 2: 下载完成后,点击运行按钮。

Python CGI Programming

步骤 - 3: 现在,点击“下一步”按钮。

Python CGI Programming

步骤 - 4: 接下来,它将显示 xampp 组件。我们可以删除其中一些,但我们将安装 xampp 的所有组件,它不会影响我们的应用程序。

Python CGI Programming

步骤 - 6: 现在,我们的设置已准备好安装,点击下一步按钮开始安装。

Python CGI Programming

它将在 Web 服务器上进行并开始安装所有软件包和文件。

Python CGI Programming

步骤 - 7: 至此,下载已完成。选择您想要的语言,然后,它将显示以下 xampp 仪表板。

Python CGI Programming

Python 安装

要安装 Python,请访问我们的 Python 安装指南 (how-to-install-python)。

第一个 CGI 程序

我们在 xampp 的 htdocs 文件夹中创建了一个名为 example 的新文件夹。然后,我们编写了一个包含 HTML 标签的 Python 脚本。让我们看看以下目录结构和 demo.py 文件。

Python CGI Programming

demo.py

以及其目录结构如下。

Python CGI Programming

在 Web 浏览器中输入 localhost/example/demo.py。它将显示以下输出。

Python CGI Programming

注意 - 我们需要启动 Apache 服务器,然后执行 CGI 脚本。我们的脚本 demo.py 默认将在主机 127.0.0.1 上运行。

让我们理解 CGI 脚本的另一个例子。

示例 - 2

Python CGI 程序的结构

让我们理解程序的以下结构。

  • CGI 脚本必须包含两个由空行分隔的部分。
  • 标头必须在第一部分,第二部分将包含将在脚本执行期间使用的数据类型。

语法图例

在 Python 中编写 CGI 程序时,请注意以下常用语法。

HTML 标头

在上述程序中,行 Content-type:text/html\r\n\r\n 是 HTTP 的一部分,我们将在 CGI 程序中使用它。

 
序号。头文件描述
1.内容类型它是一个 MIME 字符串,用于定义返回的文件格式。
2.Expires: Date它显示有效的日期信息。
3.Location: URL服务器返回的 URL。
4.Last-modified: Date它显示资源的最后修改日期。
5.Content-length: N此信息用于报告文件的估计下载时间。
6.Set-Cookies: String它用于通过字符串设置 Cookie。

CGI 环境变量

我们应该记住以下 CGI 环境变量以及 HTML 语法。让我们理解常用的 CGI 环境变量。

  • CONTENT_TYPE - 它描述数据和内容的类型。
  • CONTENT_LENGHT - 它定义查询或信息的长度。
  • HTTP_COOKIE - 它用于返回用户在当前场景中设置的 Cookie。
  • HTTP_USER_AGENT - 此变量用于显示用户当前正在使用的浏览器类型。
  • REMOTE_HOST - 它用于描述 CGI 脚本的路径。
  • PATH_INFO - 此变量用于定义 CGI 脚本的路径。
  • REMOTE_ADDR - 我们可以通过它定义访问者的 IP 地址。
  • REQUEST_METHOD - 它用于通过 POST 或 GET 发出请求。

Python CGI 编程的功能

CGI 模块提供了许多与 cgi 协作的函数。我们定义了一些重要的函数如下。

  • parse(fp = None, environ = os.environ, keep_blanks_values = False, strict_parsing = False) - 它用于解析环境中的查询。我们也可以使用文件解析它,默认文件为 sys.stdin。
  • parse_qs(qs, keep_blank_values = False, strict _parsing = False) - 虽然这已被贬低,但 Python 改用 urllib.parse.parse_qs()。
  • parse_qsl(qs, keep_blank_value = False, strict_parsing = False) - 这也已被贬低,并为了向后兼容而保留。
  • parse_multipart(fb, pdict) - 它用于解析 multipart/form-data 类型的文件上传输入。第一个参数是输入文件,第二个参数是一个字典,其中包含 content-type 标头中的其他参数。
  • parse_header(string) - 它用于解析标头。它将 MIME 标头解析为主值和参数字典。
  • test() - 它用于测试 CGI 脚本,我们可以在程序中使用它。它通常会写入最小的 HTTP 标头。
  • print_form(form) - 它以 HTML 格式化表单。
  • print_directory() - 它以 HTML 格式化当前目录。
  • escape(s, quote = False) - escape() 函数用于将字符串中的字符 '<'、'>' 和 '&' 转换为 HTML 安全序列。

调试 CGI 脚本

首先,我们需要检查简单的安装错误。大多数情况下,错误发生在 CGI 脚本的安装过程中。首先,我们必须遵循安装说明,并尝试将此模块文件 cgi.py 的副本作为 CGI 脚本安装。

接下来,我们可以使用脚本中的 test() 函数。使用单个语句键入以下代码。

CGI 编程的优点

使用 CGI 编程有多种优点。以下是其中一些优点。

  • 它们是语言独立的。我们可以将 CGI 程序与任何编程语言一起使用。
  • CGI 程序几乎可以在任何 Web 服务器上运行,并且是可移植的。
  • 它们是可移植的。
  • CGI 程序可以执行简单和复杂的任务;这意味着它们具有相当的可伸缩性。
  • CGI 可以增加 Web 应用程序中的动态通信。
  • 如果我们将 CGI 用于开发,它们也可以盈利;它们降低了开发成本和维护成本。
  • CGI 处理请求所需的时间更少。

CGI 的缺点

考虑 CGI 的以下缺点。

  • CGI 程序过于复杂且难以调试。
  • 当我们启动程序时,解释器必须在每次启动时评估 CGI 脚本。结果是,由于客户端-服务器有许多请求,会产生大量流量。
  • CGI 程序相当脆弱,因为它们大多数都是免费且易于获取,没有服务器安全性。
  • CGI 占用大量处理时间。
  • 在页面加载期间,数据不会存储在缓存内存中。
  • 存在大量的代码库,其中大部分是 Perl。

常见问题及解决方案

我们在服务器上实施 CGI 脚本时可能会遇到问题。我们列出了以下一些常见问题及其解决方案。

  • 首先,检查安装说明。大多数问题发生在服务器安装期间。请正确遵循安装指南。
  • 检查 HTTP 服务器的日志文件。在单独的窗口中使用 tail -f logfile 可能很有用。
  • 在 CGI 中,可以在客户端屏幕上显示运行请求的进度报告。大多数 HTTP 服务器会保存 CGI 脚本的输出,直到脚本完成。
  • 在执行文件之前,请检查脚本中的语法错误,例如 python script.py。
  • 如果脚本没有任何语法错误,则导入库,例如 import cgitb; cgitb.enable() 到脚本顶部。
  • 导入外部程序时必须包含绝对路径。在 CGI 脚本中,路径通常没有设置为非常有用的值。
  • 读取或写入外部文件时,请确保它们可以被运行 CGI 脚本的用户读取或写入。这是 Web 服务器正在运行的脚本文件中的授权用户 ID 或 Web 服务器的某些指定用户 ID。
  • 应该记住,CGI 脚本不得设置为 set-uid。它在大多数系统上无法工作,并且也是一个安全隐患。