cgiCommonGatewayInterfacePrecursorKnowledgeGatewayProtocolLearning:CGI,FastCGI,WSGI官方Python文档简单来说:web服务器接受请求,启动CGI;CGI接受请求,处理,返回给服务器;服务器返回给用户cgi的效率不高。每次都需要从WCGI中fork出一个新的进程,WCGI是Python搭建的桥梁,连接服务器和web框架。它完全分离了cgi的连接功能,将处理功能留给了web框架。CGI简介脚本由HTTP服务器启动,通常用于处理用户通过提交的数据。通常,CGI脚本位于服务器上的专用cgi-bin目录中。HTTP服务器将与请求相关的信息放在脚本的shell环境中,例如客户端的主机名、请求的url、请求的字符串等。服务器执行脚本并将输出返回给客户端。脚本的输入也连接到客户端,有时表单数据也是通过这种方式读取的。其他时候,表单数据通过URL的查询字符串传递。该模块用于处理不同的情况,提供了一个简单的接口。它还提供了一些功能来帮助调试脚本。最近添加的一项功能是能够通过表单上传文件。CGI脚本的输出由两部分组成,由一个空行分隔。第一部分包含一些标头,告诉客户端接下来要返回什么数据。大概是这样的:print("Content-Type:text/html")#接下来返回的是htmlprint()#空行,header结束第二部分,一般是HTML。客户端软件可以显示这些页面、图片等。使用cgi模块当你写一个新的脚本时,添加下面两行:importcgitbcigtb.enable()这将激活一个异常处理程序,如果发生错误,它会将错误返回给浏览器。如果您不希望用户看到它,您还可以指定一个输出目录。importcgitbcgitb.enable(display=0,logdir='/path/to/logdir')补充:POST请求提交数据有两种方式:application/x-www-form-urlencoded和multipart/form-data。前者为MyVariableOne=ValueOne&MyVariableTwo=ValueTwo形式,使用%HH形式编码非ascii码,不接受重复键值。后者接受重复的key-value、二进制等。参考资料可以通过FieldStorage类获取提交的表单数据。如果它包含非ascii代码,请使用编码参数。因为它会消耗标准数据,所以它应该只被实例化一次。FieldStorage实例类似于python的字典。可以使用in来检测内容,也可以使用keys和len接口。FieldStorage的每个值也是一个FieldStorage或MiniFieldStorage实例。由于表单可能有重复的项目名称,您可以使用getlist()方法。getlist(key_name)方法会返回key为key_name的所有值。如果上传的表单中有文件,可以调用value的read()函数或readline()函数。如果通过application/x-www-form-urlencoded发送数据,则没有list、file、filename接口。高级接口前面介绍过,如果你使用FieldStorage类从数据中读取CGI。本节描述了一个更具可读性和直观性的高级界面。但是,上面提到的技术仍然有用,例如高效处理文件上传。该接口包含两个方法。使用这种方法,您可以以更通用的方式处理数据,而不必担心多个值是否共享相同的名称。form=cgi.FieldStorage()item=form.getvalue("item")ifisinstance(item,list):#handlethelistpasselse:#handlethesinglevaluepass类型检查是必须的,因为会有好东西users,输入重复的键名。您可以使用高级接口提供的getfirst()和getlist()方法。函数大多数函数,例如cgi.parse、cgi.parse_qs、cgi.parse_qsl,都已移植到urllib.parse。cgi.escape被移植到html.escape。安全问题原则:如果你启动一个外部程序函数,永远不要将用户输入直接传递给shell。即使你传入它,也要确保它只包含字母和数字、破折号、下划线和点。在Unix系统上安装CGI脚本阅读HTTP服务器的文档以找到CGI脚本的安装位置,通常在服务器目录的cgi-bin目录中。确保您的脚本可以被其他程序读取和执行;在0o755的Unix文件模式中:使用chmod0755文件名。确保第一行有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:http://yourhostname/cgi-bin/c...\如果返回404错误,说明服务器没有找到这个脚本,也许您应该将它安装在另一个目录中。如果它给出其他错误,则表示您有安装问题。您应该先解决这些安装问题,然后再进行其他调试。如果它提供了非常简洁的环境变量和表单内容输出,则cgi.py已正确安装。如果你的脚本是按照上面的流程安装的,那么现在就可以调试了。下一步是在脚本中调用cgi模块的test()方法,将其主要代码替换为cgi.test。它的输出应该与仅安装cgi.py时的输出相同。当一个普通的python脚本抛出一个未处理的异常时,Python解释器打印回溯并退出。当您的CGI脚本抛出异常时,Python解释器也会做同样的事情。这些回溯通常在您的HTTP服务器的日志文件中,或者被丢弃。幸运的是,如果您的脚本执行了一些代码,您可以通过启用cgitb模块将回溯的内容发送到浏览器。将以下两行代码添加到脚本的顶部。importcgitbcgitb.enable()如果怀疑cgitb模块有问题,可以使用更健壮的方法,只调用内置模块:importsyssys.stderr=sys.stdoutprint("Content-Type:text/plain")print()以上代码依赖python解释器输出traceback,输出内容的格式指定为纯文本,去掉了HTML过程。如果您的脚本工作正常,您的客户端将显示纯HTML。如果抛出异常,回溯将在打印前两行后打印,如果没有HTML解释器正在处理它,那么回溯将是可读的。常见问题及解决方案大多数HTTP服务器将CGI脚本的输出放入缓冲区,直到脚本执行完毕,这意味着在脚本仍在执行的同时,无法在客户端显示进度检查安装过程如上即可监控日志文件首先检查语法错误如果没有语法错误,在脚本顶部添加importcgitb;cgitb.enable()启动外部程序时,确保可以找到它们。通常这意味着绝对路径名。在CGI脚本中,PATH总是设置为不带的值当脚本读写外部文件时,确保执行CGI的userid可以读写这些文件:一般来说就是运行服务器的userid,或者userid服务器的suexec。不要给CGIset-uid权限,这在大多数操作系统上是不可行的,而且不安全。