当前位置: 首页 > ops >正文

Python3(31) CGI 编程

        在 Web 开发领域,通用网关接口(CGI)为服务器与客户端之间的交互提供了有效的途径。Python 凭借其强大的功能和简洁的语法,在 CGI 编程中表现出色。这篇博客将结通过代码示例深入学习 Python3 的 CGI 编程知识,方便日后复习回顾。


一、CGI 基础概念

1.1 什么是 CGI

        CGI(Common Gateway Interface)即通用网关接口,它是运行在服务器上的一段程序,主要作用是提供服务器与客户端 HTML 页面的交互接口。比如当你在网页上点击链接或提交表单时,CGI 程序就可能在服务器端被触发,处理相关请求并返回相应结果。常见的 CGI 程序可以用 Python、PERL、SHELL、C 或 C++ 等语言编写。

1.2 CGI 工作流程

  1. 客户端请求:用户使用浏览器访问 URL,浏览器与 HTTP 服务器建立连接并发送请求信息。
  2. 服务器处理:服务器接收到请求后,解析 URL 并查找对应的文件。如果找到,就将文件内容返回给浏览器;若找不到,则返回错误信息。若请求涉及 CGI 程序,服务器会执行该程序。
  3. 浏览器显示:浏览器接收服务器返回的信息,并根据信息类型(如 HTML、文本等)进行相应显示。

二、Web 服务器支持与配置(以 Apache 为例)

在进行 Python CGI 编程前,需确保 Web 服务器支持 CGI 并完成相关配置。

设置 CGI 目录:在 Apache 服务器中,通常将 CGI 程序放在特定目录,如/var/www/cgi-bin。可以通过修改httpd.conf配置文件来指定 CGI 目录:

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

配置目录权限:确保 CGI 目录有正确的权限设置,允许服务器执行其中的脚本:

<Directory "/var/www/cgi-bin">AllowOverride NoneOptions +ExecCGIOrder allow,denyAllow from all
</Directory>

添加文件后缀支持:若想用.py作为 Python 脚本的扩展名,需在配置文件中添加相应设置:

AddHandler cgi-script .cgi .pl .py

三、第一个 CGI 程序

        下面用 Python 创建第一个 CGI 程序hello.py,保存于/var/www/cgi-bin目录:

#!/usr/bin/python3
print("Content-type:text/html")
print()  # 空行,告诉服务器结束头部
print('<html>')
print('<head>')
print('<meta charset="utf-8">')
print('<title>Hello Word - 我的第一个CGI程序!</title>')
print('</head>')
print('<body>')
print('<h2>Hello Word!我是来自菜鸟教程的第一CGI程序</h2>')
print('</body>')
print('</html>')

        后需修改文件权限为 755:

chmod 755 hello.py

        该程序向浏览器发送了 HTML 内容,其中Content-type:text/html是 HTTP 头部信息,用于告知浏览器返回内容的类型。空行用于分隔 HTTP 头部和内容主体。


四、HTTP 头部

        HTTP 头部在 CGI 程序中用于向浏览器传递重要信息,常见的头部信息如下:

描述示例
Content-type请求的与实体对应的 MIME 信息Content-type:text/html
Expires响应过期的日期和时间Expires: Wed, 28 Aug 2016 18:30:00 GMT
Location重定向接收方到非请求 URL 的位置Location: http://www.example.com/newpage
Last-modified请求资源的最后修改时间Last-modified: Tue, 15 Nov 2022 10:00:00 GMT
Content-length请求的内容长度Content-length: 1024
Set-Cookie设置 Http CookieSet-Cookie: name="value"; expires=date; path=path; domain=domain; secure

五、CGI 环境变量

        CGI 程序会接收一系列环境变量,这些变量包含了客户端和服务器的相关信息,在编程中十分重要。例如:

  • CONTENT_TYPE:指示传递来的信息的 MIME 类型,常见值为application/x-www-form-urlencoded,表示数据来自 HTML 表单。
  • QUERY_STRING:若服务器与 CGI 程序通过 GET 方式传递信息,该变量保存传递的信息,信息跟在 CGI 程序名后,以?分隔。

        下面的 CGI 脚本用于输出所有 CGI 环境变量:

#!/usr/bin/python3
import os
print("Content-type: text/html")
print()
print("<meta charset=\"utf-8\">")
print("<b>环境变量</b><br>")
print("<ul>")
for key in os.environ.keys():print("<li><span style='color:green'>%30s </span> : %s </li>" % (key, os.environ[key]))
print("</ul>")

        保存为test.py并修改权限后,在浏览器中访问可查看环境变量信息。


六、GET 和 POST 方法

        浏览器通过 GET 和 POST 方法向服务器传递信息,二者在使用上有一定区别。

6.1 GET 方法

        GET 方法将用户信息编码后附加在 URL 上传递给服务器,例如:http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2。GET 方法的特点如下:

  • 可被缓存,会保留在浏览器历史记录中,还能被收藏为书签。
  • 有长度限制,不适合处理敏感数据,主要用于取回数据。

        下面是一个使用 GET 方法传递参数的 CGI 程序hello_get.py

#!/usr/bin/python3
import cgi, cgitb
form = cgi.FieldStorage()
site_name = form.getvalue('name')
site_url = form.getvalue('url')
print("Content-type:text/html")
print()
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>菜鸟教程CGI测试实例</title>")
print("</head>")
print("<body>")
print("<h2>%s官网:%s</h2>" % (site_name, site_url))
print("</body>")
print("</html>")

        可以通过 URL 直接传递参数,也可以通过 HTML 表单(设置method="get")传递参数。

6.2 POST 方法

        POST 方法将数据放在请求体中传递,相比 GET 方法更安全可靠,适合传递敏感信息。hello_get.py同样可以处理 POST 方法提交的数据,只需将 HTML 表单的method属性改为post即可。


七、传递不同类型数据

7.1 checkbox 数据

        checkbox 用于提交多个选项数据,HTML 代码示例:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><form action="/cgi-bin/checkbox.py" method="POST" target="_blank"><input type="checkbox" name="runoob" value="on" />菜鸟教程<input type="checkbox" name="google" value="on" />Google<input type="submit" value="选择站点" /></form>
</body>
</html>

        对应的 Python 脚本checkbox.py

#!/usr/bin/python3
import cgi, cgitb
form = cgi.FieldStorage()
if form.getvalue('google'):google_flag = "是"
else:google_flag = "否"
if form.getvalue('runoob'):runoob_flag = "是"
else:runoob_flag = "否"
print("Content-type:text/html")
print()
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>菜鸟教程CGI测试实例</title>")
print("</head>")
print("<body>")
print("<h2>菜鸟教程是否选择了 : %s</h2>" % runoob_flag)
print("<h2>Google是否选择了 : %s</h2>" % google_flag)
print("</body>")
print("</html>")

7.2 Radio 数据

        Radio 只传递一个数据,HTML 代码示例:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><form action="/cgi-bin/radiobutton.py" method="post" target="_blank"><input type="radio" name="site" value="runoob" />菜鸟教程<input type="radio" name="site" value="google" />Google<input type="submit" value="提交" /></form>
</body>
</html>

  radiobutton.py脚本代码:

#!/usr/bin/python3
import cgi, cgitb
form = cgi.FieldStorage()
if form.getvalue('site'):site = form.getvalue('site')
else:site = "提交数据为空"
print("Content-type:text/html")
print()
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>菜鸟教程CGI测试实例</title>")
print("</head>")
print("<body>")
print("<h2>选中的网站是 %s</h2>" % site)
print("</body>")
print("</html>")

7.3 Textarea 数据

        Textarea 用于传递多行数据,HTML 代码示例:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><form action="/cgi-bin/textarea.py" method="post" target="_blank"><textarea name="textcontent" cols="40" rows="4">
在这里输入内容...</textarea><input type="submit" value="提交" /></form>
</body>
</html>

  textarea.py脚本代码:

#!/usr/bin/python3
import cgi, cgitb
form = cgi.FieldStorage()
if form.getvalue('textcontent'):text_content = form.getvalue('textcontent')
else:text_content = "没有内容"
print("Content-type:text/html")
print()
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>菜鸟教程CGI测试实例</title>")
print("</head>")
print("<body>")
print("<h2>输入的内容是:%s</h2>" % text_content)
print("</body>")
print("</html>")

7.4 下拉数据

        HTML 下拉框代码示例:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><form action="/cgi-bin/dropdown.py" method="post" target="_blank"><select name="dropdown"><option value="runoob" selected>菜鸟教程</option><option value="google">Google</option></select><input type="submit" value="提交"/></form>
</body>
</html>

  dropdown.py脚本代码:

#!/usr/bin/python3
import cgi, cgitb
form = cgi.FieldStorage()
if form.getvalue('dropdown'):dropdown_value = form.getvalue('dropdown')
else:dropdown_value = "没有内容"
print("Content-type:text/html")
print()
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>菜鸟教程CGI测试实例</title>")
print("</head>")
print("<body>")
print("<h2>选中的选项是:%s</h2>" % dropdown_value)
print("</body>")
print("</html>")

八、CGI 中使用 Cookie

8.1 Cookie 设置

        Cookie 用于在客户端存储少量数据,弥补了 HTTP 协议无状态的不足。设置 Cookie 通过 HTTP 头部的Set-Cookie实现,示例代码cookie_set.py

#!/usr/bin/python3
print('Set-Cookie: name="菜鸟教程";expires=Wed, 28 Aug 2016 18:30:00 GMT')
print('Content-Type: text/html')
print()
print("""
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><h1>Cookie set OK!</h1>
</body>
</html>
""")

8.2 检索 Cookie 信息

        检索 Cookie 信息需通过 CGI 环境变量HTTP_COOKIE,示例代码cookie_get.py

#!/usr/bin/python3
import os
import http.cookies
print("Content-type: text/html")
print()
print("""
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>读取cookie信息</h1>
""")
if 'HTTP_COOKIE' in os.environ:cookie_string = os.environ.get('HTTP_COOKIE')c = http.cookies.SimpleCookie()c.load(cookie_string)try:data = c['name'].valueprint("cookie data: " + data + "<br>")except KeyError:print("cookie没有设置或者已过去<br>")
print("""
</body>
</html>
""")

九、文件上传与下载

9.1 文件上传

        HTML 表单需设置enctype="multipart/form-data"来实现文件上传,示例代码:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title>
</head>
<body><form enctype="multipart/form-data" action="/cgi-bin/save_file.py" method="post"><p>选中文件: <input type="file" name="filename" /></p><p><input type="submit" value="上传" /></p></form>
</body>
</html>

        对应的 Python 脚本save_file.py

#!/usr/bin/python3
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
fileitem = form['filename']
if fileitem.filename:fn = os.path.basename(fileitem.filename)open('/tmp/' + fn, 'wb').write(fileitem.file.read())message = '文件 "' + fn + '" 上传成功'
else:message = '文件没有上传'
print("""\
Content-Type: text/html\n
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body><p>%s</p>
</body>
</html>
""" % (message,))

9.2 文件下载

        文件下载通过设置 HTTP 头信息Content-Disposition实现,示例代码:

#!/usr/bin/python3
# HTTP头部
print("Content-Disposition: attachment; filename=\"foo.txt\"")
print()
# 打开文件
fo = open("foo.txt", "rb")
str = fo.read()
print(str)
# 关闭文件
fo.close()

十、总结

        Python3 的 CGI 编程为 Web 开发提供了一种强大的交互方式,通过掌握 CGI 的基础概念、Web 服务器配置、不同数据传递方式、Cookie 使用以及文件上传下载等知识,可以构建出功能丰富的 Web 应用程序。在实际开发中,应根据具体需求选择合适的方法,并注意安全和性能问题。希望这篇博客能帮助你更好地复习和巩固 Python3 CGI 编程知识,在 Web 开发领域灵活运用。

http://www.xdnf.cn/news/5473.html

相关文章:

  • 自动驾驶技术栈——DoIP通信协议
  • 鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
  • 【数据结构】——队列
  • 学习threejs,使用Physijs物理引擎,加载各种几何体网格对象
  • 2025 盘古石杯初赛 wp
  • Lambda表达式能用在哪些场景?
  • 学习黑客5 分钟深入浅出理解Windows Editions
  • MyBatis源码解读1(MyBatis回顾)
  • 微调重排序模型:Reranking从入门到实践
  • GPU Gems1-Effective Water Simulation from Physical Models
  • RHCSA Linux系统 Web页面 论坛 网盘的搭建
  • 沈燕谈艺:把现代科学基因融入古典笔墨中
  • OrangePi Zero 3学习笔记(Android篇)6 - hid-ft260
  • Redis设计与实现——单机Redis实现
  • 光线传感器BH1750
  • springboot3学习
  • 部署Superset BI(五)连接oracle数据库失败
  • LangChain入门(七) 提取和输出结构化数据
  • 【计算机视觉】基于深度学习的实时情绪检测系统:emotion-detection项目深度解析
  • Day116 | 灵神 | 二叉树 | 二叉搜索树中第K小的元素
  • 软件测试复习第五章
  • 利用类型别名定义复杂联合类型和交叉类型
  • cheat engine: Scan error no readable memory found
  • 学习通刷课稳定版(美化面板+完全免费)
  • 【RP2350】香瓜树莓派RP2350之新建工程
  • JAVA 锁—— synchronized
  • linux 三剑客命令学习
  • C++基本知识 —— 缺省参数·函数重载·引用
  • 蓝桥杯14届国赛 合并数列
  • 【Python 算法零基础 2.模拟 ⑤ 基于栈和队列】