通读Python官方文档之cgi
cgi 通用网关接口
前驱知识
简单点说:
- web服务器接受请求,启动
CGI;CGI接受请求,处理,返回给服务器;服务器返回给用户 - cgi效率不高,每次都要
fork一个新进程出来 WCGI,Python架设的一个桥,连接了服务器和web框架,相当将cgi的连接功能独立了出来,并把处理功能留给了web框架
简介
CGI脚本由HTTP服务器启动,通常用来处理用户通过<FROM>提交的数据。
通常,CGI脚本位于服务器的专门的cgi-bin目录下。HTTP服务器在脚本的shell环境中放置了请求相关的信息,比如客户端的hostname,请求的url,请求的字符串以及其他东西。服务器执行脚本,并把输出返回给客户端。
脚本的输入也和客户端相连,有时表单数据是通过这种方式读取的。其他时候,表单数据是通过URL的query字符串传递的。这个模块用于处理不同的情况,提供一个简单的接口。同时提供了一些功能,帮助调试脚本。最近添加的功能是通过表单上传文件。
CGI脚本的输出由两部分组成,由一个空行分割。第一部分包含一些头部,告诉客户接下来返回的是什么数据。大概是这样:
print("Content-Type: text/html") # 接下来返回的是html
print() # 空白行,头部结束
第二部分,一般来说是HTML。客户端软件可以展示这些页面,图片什么的。
使用cgi模块
当你写一个新的脚本时,添加下面这两行:
import cgitb
cigtb.enable()
这将会激活一个异常处理器,如果发生了错误,它就会把错误返回给浏览器。如果你不想让用户看到,也可以指定输出目录。
import cgitb
cgitb.enable(display=0, logdir='/path/to/logdir')
补充:
POST请求提交数据有两种方式application/x-www-form-urlencoded和multipart/form-data。前者形如MyVariableOne=ValueOne&MyVariableTwo=ValueTwo,使用%HH的形式编码非ascii码,不接受重复键值。后者接受重复键值、二进制文件等。参考资料
可以通过FieldStorage类获取提交的表单数据,如果含有非asciii码,使用encoding参数,由于它会消耗标准数据,所以应该只被实例化1次。
FieldStorage实例与python的字典相似。可以使用in检测内容,keys, len接口也都可以使用。FieldStorage的每个值也是一个FieldStorage或者MiniFieldStorage实例。
由于表单可能存在重复的项目名,你可以使用getlist()方法。getlist(key_name)方法会返回所有key为key_name的值。
如果上传的表单中存在文件,你可以调用值的read()函数或者readline()函数。
如果是通过application/x-www-form-urlencoded发送的数据,则没有list, file, filename接口。
高级接口
前面介绍了,如果使用FieldStorage类从数据读取CGI。这一节,讲述以西而更可读和符合直觉的高级接口。但,前面讲的技术还是有用的,比如高效处理文件上传。
该接口包含两个方法。使用这戏方法你可以以更一般的方式处理数据,不用担心是否有几个值公用一个名字。
form = cgi.FieldStorage()
item = form.getvalue("item")
if isinstance(item, list):
# handle the list
pass
else:
# handle the single value
pass
进行类型检查是必须的,因为会有好事的用户,输入重复的键名。
你可以使用高级接口提供的getfirst()和getlist()方法。
函数
大部分函数,如cgi.parse,cgi.parse_qs,cgi.parse_qsl,已经被移植到urllib.parse。 cgi.escape被移植到html.escape。
安全问题
原则:如果你启动了一个外部程序函数,永远不要把用户的输入直接传入shell。即使要传入也要确保只含有字母和数字、横杠、下划线和点。
在Unix系统上安装CGI脚本
阅读你的HTTP服务器的文档,找到你的CGI脚本的安装位置,一般是在服务器目录的cgi-bin目录下。
确保你的脚本可被其他程序读和执行;在Unix文件模式下处于0o755:使用chmod 0755 filename。确保第一行有shebang:
#! /usr/local/bin/python
同时,你的脚本需要执行的文件都有对应的权限。因为你的服务器被用户nobody执行,它只能读/写/执行那些被所有人读/写/执行的文件。当前目录和系统环境变量也可能可你目前所处的不一样。
如果你需要从别的目录引用模块,使用sys.path.insert(0, "/path/to/your/module")这样你的模块会被首先搜索。
测试你的CGI脚本
不行的是,当你从命令行尝试CGI脚本是,它很有可能不会运行,而一个能运行的CGI脚本往往在服务器中不能运行。但你仍然应该从命令行中运行脚本,检查一下他是否有语法错误。如果你的脚本没有语法错误,但是它不工作,你只能读下一节。
调试CGI脚本
首先,检查一下琐碎的安装错误,读一下上面关于安装的部分,能节约时间。如果你想知道你是否正确理解了安装过程,把这个模块文件cgi.py安装到你的cgi脚本目录下,启动这个脚本,他就会将它的环境和内容以HTML的格式输出。给他一个合适的模式,发送给他一个请求。如果它被安装在cgi-bin目录下,在你的浏览器内输入如下url:
如果返回404错误,则说明服务器没有找到这个脚本,或许你应该把它装在别的目录下。如果给了别的错误,说明你有安装问题。你应该首先解决这些安装问题,再做别的调试。如果它给出了非常整洁的环境变量和表单内容输出,说明cgi.py被正确的安装了。如果,你的脚本按上述过程安装,你现在可以对他进行调试了。
下一步是在你的脚本中调用cgi模块的test()方法,把它的主要代码替换成cgi.test。
它应该输出和仅安装cgi.py时一致。
当一个普通的python脚本抛出了一个未处理的异常时,Python解释器会把traceback打印出来,退出。当你的CGI脚本抛出异常时,Python解释器也会这么做。这些traceback一般会在你的HTTP服务器的日志文件里,或者被丢弃了。
幸运的是,如果你的脚本执行了某些代码,你可以通过启用cgitb模块,把traceback的内容发送到浏览器中。把下面两行代码加到你脚本的顶部。
import cgitb
cgitb.enable()
如果你怀疑cgitb模块有问题,你可以使用一个更鲁棒的方法,只调用内置模块:
import sys
sys.stderr = sys.stdout
print("Content-Type: text/plain")
print()
上述代码依赖python解释器输出traceback,输出的内容的格式被指定为纯文本,去除了HTML过程。如果你的脚本正常工作,你的客户端会显示纯HTML。如果抛出了异常,前两行打印出之后,traceback会被打印出来,如果没有HTML解释器进行处理,所以traceback会可读。
常见问题及解决
- 大多数HTTP服务器将
CGI脚本的输出放入缓冲区直至脚本完成,这意味着在脚本还在执行时,不可能在客户端展示进度 - 按上述核对安装过程
- 监控日志文件
- 先检查语法错误
- 如果没有语法错误,在脚本顶部添加
import cgitb; cgitb.enable() - 当启动外部程序时,确保他们能够被找到,通常这意味着绝对路径名,在
CGI脚本中,PATH总是被设置为一个没啥用的值 - 当脚本读写外部文件是,确保执行
CGI的userid能够读写这些文件:一般来说是运行服务器的的userid,或者是服务器的suexec的userid - 不要给一个
CGIset-uid权限,这在大多数操作系统上不可行,而且不安全。
通读Python官方文档之cgi的更多相关文章
- 通读Python官方文档之wsgiref(未完成)
wsgirf-WSGI功能及参考实现 源码:Lib/wsgiref Web服务器网关接口(Web Server Gateway Interface, WSGI),是用Python写的一个服务器软件和w ...
- 通读Python官方文档之cgitb
cgitb CGI脚本异常管理 源代码:Lib/cgitb.py cgitb模块为Python脚本提供了一个特殊的异常管理器.名字有点误导人,它最初设计是为了以HTML格式展示cgi脚本的大量异常信息 ...
- 别开心太早,Python 官方文档的翻译差远了
近几天,很多公众号发布了 Python 官方文档的消息.然而,一个特别奇怪的现象就发生了,让人啼笑皆非. Python 文档的中文翻译工作一直是“默默无闻”,几个月前,我还吐槽过这件事<再聊聊P ...
- 阅读Python官方文档心得
我会每天都阅读一些python的官方文档,并每天更新心得体会. -------------------------------------------------2016.12.08--------- ...
- [Python3]Python官方文档-Python Manuals
简介 一般情况下,初学者都不愿意直接去浏览Python Manuals,即Python自带的官方文档.尤其是只有英文版的情况下,初学者更加不会去使用该官方文档了. 在这里笔者强力推荐初学者经常学会使用 ...
- PEP 324 subprocess 新的进程模块 -- Python官方文档译文 [原创]
PEP 324 -- subprocess 新的进程模块(subprocess - New process module) 英文原文:https://www.python.org/dev/peps/p ...
- python官方文档
Tutorialstart here Library Referencekeep this under your pillow Language Referencedescribes syntax a ...
- Python 官方文档解读(2):threading 模块
使用 Python 可以编写多线程程序,注意,这并不是说程序能在多个 CPU 核上跑.如果你想这么做,可以看看关于 Python 并行计算的,比如官方 Wiki. Python 线程的主要应用场景是一 ...
- Python 官方文档解读(1):66 个内置函数
Python 解释器 (CPython 3.7)内置有 66 个函数,这些函数在任何时刻都是可用的.此文是为了对这 66 个函数进行简单的梳理,便于以后可能用到它们时能想到. 1. abs(x) 返回 ...
随机推荐
- 【ES6 】Promise
Promise对象定义: 用来处理异步编程 Promise对象的特点 对象的状态不受外界影响 一旦状态改变,就不会再变,任何时候都可以得到这个结果 Promise对象的状态 pending(进行中) ...
- idea内存溢出解决方法
在Run/Debug configuration 的vm options里面输入 -server -XX:PermSize=128M -XX:MaxPermSize=256m eclipse: -Xm ...
- mybatis整合spring下的的各种配置文件
1.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...
- GSM AT指令 SIM900A TC35
http://download.csdn.net/download/zhangxuechao_/9911264 短信 TEXT格式 设置短消息中心号码: AT+CSCA="+86130101 ...
- Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)
详见:https://www.w3cschool.cn/spring_cloud/spring_cloud-jl8a2ixp.html 上一篇文章,留了一个悬念,Config Client 实现配置的 ...
- Dart 面向对象 类 方法
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类. 面向对象编程(OOP)的三个基本特征是:封装.继承.多态 封装:封装是对象和类概念的主要特性. ...
- Redis安装及前后置启动
Redis简单介绍及在Linux上安装(这里测试用是版本:redis-3.0.0.tar.gz) 一:什么是Redis? redis就是C语言编写的一个高性能的键值存储(key-value)的非关系型 ...
- 多线程threading模块
python的多线程编程 简介 多线程编程技术可以实现代码并行性,优化处理能力,同时功能的更小划分可以使代码的可重用性更好.Python中threading和Queue模块可以用来实现多线程编程. 详 ...
- PMM 监控 MySQL
Percona Monitoring and Management (PMM)是一款开源的用于监控 MySQL 和 MongoDB 性能的开源平台,通过 PMM 客户端收集到的 DB 监控数据用第三方 ...
- 01.CNN调参
转载:调参是个头疼的事情,Yann LeCun.Yoshua Bengio和Geoffrey Hinton这些大牛为什么能够跳出各种牛逼的网络? 下面一些推荐的书和文章:调参资料总结Neural Ne ...