版权声明:本文为博主原创文章,转载本站文章请注明作者和出处,请勿用于任何商业用途。 https://blog.csdn.net/wutianxu123/article/details/82560873
17.1 理论基础
CGI工作原理:(通用网关接口)
1、web服务器从客户端接到了请求(即GET或者POST),并调用相应的CGI应用程序。
2、等待HTML页面,与此同时,客户端也在等待。
3、一旦应用程序处理完成,它会将生成的动态HTML页面返回服务器端,然后服务器端再将这个最终结果返回给用户。
需要注意的是,由于CGI有明显的局限性,以及限制Web服务器同时处理客户端的数量,因此一般生产环境的web应用都不再使用CGI了。
CGI应用程序:
与典型应用程序区别在于,输入、输出及用户和计算机交互。所有交互都发生在Web客户端(用户的行为)、Web服务器端和CGI应用程序间。
主要模块:
import cgi
import cgitb
17.2 CGI应用程序
启动最基本的web服务器:
python -m CGIHTTPServer 8000 #8000是端口号
然后按照如下步骤放置文件:
1、在D:\mypython下新建文件夹cgi-bin,为D:\mypython\cgi-bin
2、在D:\mypython\cgi-bin\下放入.py脚本(结果页面)
3、在D:\mypython\下放入.html文件(表单页面)。该文件与cgi-bin平级
4、浏览器输入<http://localhost:8000/friends.html>打开页面
5、输入搜索内容进行搜索,搜索将调用在D:\mypython\cgi-bin\下的.py脚本
更加简单的方式:
1、抛弃.html文件,将其集成到.py文件中
2、浏览器输入<http://localhost:8000/cgi-bin/friendB.py>打开页面
3、现在该脚本同时生成并控制了表单页面和结果页面
代码实例:
#!/usr/bin/env python
#-*-coding: utf-8-*-
import cgi
header = 'Content-Type: text/html\n\n'
#表单页面变量,包含三个变量action、person和howmany,其中action变量的值在表单页面中是'edit',action变量在这里的作用是作为一个表单页面的标识
formhtml = '''
<HTML>
<HEAD>
<meta charset="UTF-8"> <!--html注释格式!该句为中文标识-->
<TITLE>这是一个CGI例子</TITLE>
</HEAD>
<BODY>
<H3>
搜索框如下: <I>输入搜索的内容</I>
</H3>
<FORM ACTION="/cgi-bin/friendsB.py">
<B>你的搜索内容:</B>
<INPUT TYPE=hidden NAME=action VALUE=edit>
<INPUT TYPE=text NAME=person VALUE="NEW USER" SIZE=15>
<P>
<B>要展示多少搜索结果:</B>%s
</P>
<INPUT TYPE=submit>
</FORM>
</BODY>
</HTML>'''
fradio = '<INPUT TYPE=radio NAME=howmany VALUE="%s" %s> %s\n' #创建单选按钮的字符串变量
def showForm(): #生成表单页面用于用户输入
friends = []
for i in (0, 10, 25, 50, 100): #创建单选按钮文字集
checked = ''
if i == 0:
checked = 'CHECKED'
friends.append(fradio % (str(i), checked, str(i)))
print '%s%s' % (header, formhtml % ''.join(friends)) #将friend合并到formhtml中
#结果页面变量,只有两个变量person和howmany
reshtml = '''
<HTML>
<HEAD>
<meta charset="UTF-8"> <!--html注释格式!该句为中文标识-->
<TITLE>这是一个CGI例子</TITLE>
</HEAD>
<BODY>
<H3>
您搜索的内容如下: <I>%s</I>
</H3>
您输入的内容是: <B>%s</B>
<P> <!--html注释格式!该句为另起一行-->
您想展示 <B>%s</B> 个结果
</p>
</BODY>
</HTML>'''
def doResults(who, howmany):
print header + reshtml % (who, who, howmany)
def process():
form = cgi.FieldStorage() #读取有关的用户信息,在本例就是action、person和howmany这三个键值对
if 'person' in form:
who = form['person'].value
else:
who = 'NEW USER'
if 'howmany' in form:
howmany = form['howmany'].value
else:
howmany = 0
if 'action' in form:
doResults(who, howmany)
else: #程序第一次运行时,并没有向cgi应用程序提交表单,所以form是不会有action这个键的
showForm()
if __name__ == '__main__':
process()
更加完整的例子:页面添加了一个返回链接,使得用户可以从结果页面返回到表单页面,且返回后用户之前输入的信息依然存在。同时添加了一个错误处理页面,如果搜索内容未设置将跳转至错误处理页面进行提示。
注意:与之前的代码段有所不同
#!/usr/bin/env python
#-*-coding: utf-8-*-
import cgi
from urllib import quote_plus #新增了库
header = 'Content-Type: text/html\n\n'
url = '/cgi-bin/friendsC.py' #单独抽出是因为表单页面和结果页面都会用到
errhtml = ''' <!--html注释格式!错误处理页面-->
<HTML>
<HEAD>
<meta charset="UTF-8"> <!--html注释格式!该句为中文标识-->
<TITLE>这是一个CGI例子</TITLE>
</HEAD>
<BODY>
<H3>错误!</H3>
<B>%s</B>
<P>
<FORM>
<INPUT TYPE=button VALUE=返回 ONCLICK="window.history.back()">
</FORM>
</p>
</BODY>
</HTML>'''
def showError(error_str):
print header + errhtml % error_str
formhtml = '''
<HTML>
<HEAD>
<meta charset="UTF-8"> <!--html注释格式!该句为中文标识-->
<TITLE>这是一个CGI例子</TITLE>
</HEAD>
<BODY>
<H3>
搜索框如下: <I>%s</I>
</H3>
<FORM ACTION="%s">
<B>你的搜索内容:</B>
<INPUT TYPE=hidden NAME=action VALUE=edit>
<INPUT TYPE=text NAME=person VALUE="%s" SIZE=15>
<P>
<B>要展示多少搜索结果:</B>%s
</P>
<INPUT TYPE=submit>
</FORM>
</BODY>
</HTML>'''
fradio = '<INPUT TYPE=radio NAME=howmany VALUE="%s" %s> %s\n' #单选按钮
def showForm(who, howmany): #生成表单页面用于用户输入
friends = []
for i in (0, 10, 25, 50, 100): #创建单选按钮文字集
checked = ''
if str(i) == howmany: #方便用户更新数据,所以这里的howmany依然是用户上次选定的数据,而非默认的0
checked = 'CHECKED'
friends.append(fradio % (str(i), checked, str(i)))
print '%s%s' % (header,formhtml % (who,url,who,''.join(friends)))
reshtml = '''
<HTML>
<HEAD>
<meta charset="UTF-8"> <!--html注释格式!该句为中文标识-->
<TITLE>这是一个CGI例子</TITLE>
</HEAD>
<BODY>
<H3>
您搜索的内容如下: <I>%s</I>
</H3>
您输入的内容是: <B>%s</B>
<P> <!--html注释格式!该句为另起一行-->
您想展示 <B>%s</B> 个结果.
</P>
单击<A HREF="%s">这里</A>再次编辑您的数据.
</BODY>
</HTML>'''
def doResults(who, howmany):
newurl = url+'?action=reedit&person=%s&howmany=%s' % (quote_plus(who),howmany) #设置新的url是为了方便用户更新数据
print header + reshtml % (who, who, howmany, newurl)
def process():
error = ''
form = cgi.FieldStorage()
if 'person' in form:
who = form['person'].value.title()
else:
who = 'NEW USER'
if 'howmany' in form:
howmany = form['howmany'].value
else:
if 'action' in form and form['action'].value == 'edit': #只输入person变量,而不选择howmany,就会连接到错误页面
error = '请设置搜索结果的展示数量'
else:
howmany = 0
if not error:
if 'action' in form and form['action'].value != 'reedit':
doResults(who, howmany)
else:
showForm(who, howmany)
else:
showError(error)
if __name__ == '__main__':
process()
17.3 WSGI-web服务器网关接口
背景:
CGI进程针对每个请求进行创建,用完就抛弃。如果请求过多则服务器宕机。
解决办法:
一是服务器集成(Apache),二是外部进程(CGI在服务器外部运行)。
WSGI:
是定义的一个接口。其目标是在Web服务器和Web框架层之间提供一个通用的API标准,减少之间的互操作性并形成统一的调用方式。
中间件:
位于web服务器和web应用之间,在应用执行前或执行后添加一些额外的功能。
WSGI的主旨:
是在Web应用和Web服务器之间做了明显的分割。这样有利于分块开发,让团队更方便地划分任务,让Web应用能以一致且灵活的方式在任何兼容WSGI的后端中运行。