Python核心编程笔记————Web 编程:CGI 和 WSGI(一)

帮助 Web 服务器处理客户端数据

CGI简介

. Web 最初目的是在全球范围内对文档进行在线存储和归档(大多用于教学和科研)。这些文件通常用静态文本表示,一般是 HTML。随着因特网和 Web 服务的发展,除了浏览之外,还需要处理用户的输入。
  现在服务器的处理过程一般是:第一步Web服务器从客户端接受到请求(GET或POST),并调用相应的程序;然后等待HTML页面,与此同时客户端也在等待;当应用程序处理完成,会将动态生成的HTML页面返回服务器端;然后服务器再将这个结果返回给用户。
  创建 HTML 的 CGI 应用程序通常是用高级编程语言来实现的,可以接受、处理用户数据,向服务器端返回 HTML 页面。在接触 CGI 之前,需要告诫的是,一般生产环境的 Web应用都不再使用 CGI 了。 如今 Web 服务器典型的部件有 Apache 和集成的数据库访问部件(MySQL 或者 PostgreSQL)、Java(Tomcat)、PHP和各种动态语言(如 Python 或 Ruby)模块,以及 SSL/security。

CGI 应用程序

. CGI 应用程序和典型的应用程序有些不同,主要的区别在于输入、输出以及用户和程序交互方面。
  CGI应用程序的输入是从Web 客户端获得的用户提供的表单数据,而不是从服务器或者硬盘上获得;
  CGI应用程序的输出将会发送回连接的 Web 客户端,而不是发送到屏幕、GUI窗口或者硬盘上。这些返回的数据必须是具有一系列有效头文件的 HTML 标签数据;
  CGI应用程序中,用户与脚本之间没有任何交互。所有的交互都将发生在 Web 客户端(基于用户的行为)、Web 服务器端和 CGI 应用程序间。

cgi 模块

. cgi 模块中有个主要类:FieldStorage 类,其完成了所有的工作。Python CGI脚本启动的时候实例化这个类,实例化完成后,其中会包含一个类似字典的对象,它具有一系列键值对,键是通过表单传入的表单条目的名字,值则包含相应的数据。
  这些值可以是以下三种对象之一:
  1.FieldStorage对象;
  2.另一个名为MiniFieldStorage 类的类似实例,用在没有文件上传或 mulitple-part 格式数据的情况下;
  3.它们还可以是这些对象的列表。当表单中的某个字段有多个输入值时就会产生这种对象。

cgitb 模块

. Web 服务器在收到无法理解的响应时,会抛弃这个响应,返回“500 错误”。500 是一个HTTP 响应编码,它表示发生了一个内部服务器错误。一般是服务器所执行的应用程序发生了错误。此时在浏览器中给出的提示消息没什么用,要么是空白,要么显示“内部服务器错误”或类似消息。
  当 Python 程序在命令行或集成开发环境(IDE)中运行时,发生的错误会生成回溯消息,指出错误发生的位置,在浏览器中不会显示回溯消息。若想在浏览器中看到的是 Web 应用程序的回溯信息,而不是“内部服务器错误”,可以使用 cgitb 模块。其使用方法只需要将下面代码插入CGI程序中并调用:

import cgitb
cgitb.enable()

构建CGI应用程序

. 为了用 Python 进行 CGI 开发,首先需要安装一个 Web 服务器,将其配置成可以处理Python CGI 请求,然后让 Web 服务器访问 CGI 脚本。
  生产环境中的服务器。如果需要一个真正的 Web 服务器,可以下载并安装 Apache、ligHTTPD 或 thttpd。Apache中有许多插件或模块可以处理 Python CGI;
  开发人员服务器。出于学习目的或者想建立小型 Web 站点,使用 Python 自身带的 Web 服务器就已经足够,在Python3中构建步骤如下:
  1.在建好的文件夹下打开cmd窗口,进入python命令窗口下输入:

python -m http.server --cgi

. 2.在该文件夹下建立新文件夹,命名为cgi-bin;
  3.将python脚本放入该文件夹下,就可以在浏览器中输入:
  http://localhost:8000/cgi-bin/xxx.py来查看。

静态表单页

. 接下来的例子是创建一个静态的页面,获取用户的输入,将交互行为交给后面的python脚本,得到处理结果后在显示出来:
  第一步:创建静态页面。在打开端口的文件夹目录下创建friend.html文件如下:

<HTML><HEAD><TITLE>
friends CGI demon
</TITLE></HEAD>
<BODY><H3>Friends list for:<I>NEW user</I></H3>
<FORM ACTION = "/cgi-bin/friends.py">
<B>Enter Your Name:</B>
<INPUT TYPE = text NAME = person VALUE = "new user" SIZE = 15>
<p><B>How Many Friends Do You Have?</B>
<INPUT TYPE = radio name = howmany value = "0" checked>0
<INPUT TYPE = radio name = howmany value = "10" >10
<INPUT TYPE = radio name = howmany value = "20" >20
<INPUT TYPE = radio name = howmany value = "30" >30
<INPUT TYPE = radio name = howmany value = "40" >40
<p><INPUT TYPE = submit></FORM></BODY></HTML>

. 第二步,在cgi-bin目录下创建friends.py脚本:

import cgi

reshtml = '''Content-Type: text/html\n
<html><head><title>
Friends CGI demon (dynamic)
</title></head>
<body><h3>Friend list for:<i>%s</i></h3>
Your name is: <b>%s</b><p>
you have <b>%s</b>friends.
</body></html>'''

form = cgi.FieldStorage()
who = form['person'].value
howmany = form['howmany'].value
print(reshtml % (who,who,howmany))

. 第三步,在浏览器搜索栏输入:http://localhost:8000/friend.html打开静态页面后,输入相应选项,点击submit按钮,将会调用python脚本生成结果页面。

动态表单页

. 接下来的例子将html文件舍弃,表单页和结果都有python脚本生成:

import cgi

header = 'Content-Type: text/html\n\n'

formhtml = '''<html><head><tltle>
Friends CGI demon</title></head>
<body><h3>Friends list for :<i>new user</i></h3>
<form action = "/cgi-bin/friendsb.py">
<b>enter your name:</b>
<input type = hidden name = action value = edit>
<input type = text name = person value = "new user" size = 15>
<p><b>how many friends do you have?</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,20,30,40):
        checked = ''
        if i == 0:
            checked = 'CHECKED'
        friends.append(fradio % (str(i),checked,str(i)))
    print('%s%s' % (header,formhtml % ''.join(friends)))    #join函数使得friends中每个元素以''连接

reshtml = '''<html><head><tltle>
Friends CGI demon</title></head>
<body><h3>Friends list for:<i>%s</i></h3>
your name is: <b>%s</b><p>
you have <b>%s</b> friends.
</body></html>
'''

def doresult(who,howmany):
    print(header + reshtml % (who,who,howmany))

def process():
    form = cgi.FieldStorage()
    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:
        doresult(who,howmany)
    else:
        showForm()

if __name__ == '__main__':
    process()

全面交互的文本站点

. 最后的例子对代码做了更多的完善,只是逻辑上的,没有新知识:

import cgi
import urllib

header = 'Content-Type: text/html\n\n'
url = "/cgi-bin/friendsc.py"

errhtml = '''html><head><tltle>
Friends CGI demon</title></head>
<body><h3>Error</h3>
<b>%s</b><p>
<form><input type = button value = Back
ONCLICK = "window.history.back()"></form>
</body></html>
'''

def showErr(err_str):
    print(header + errhtml % err_str)


formhtml = '''<html><head><tltle>
Friends CGI demon</title></head>
<body><h3>Friends list for :<i>%s</i></h3>
<form action = "%s">
<b>enter your name:</b>
<input type = hidden name = action value = edit>
<input type = text name = person value = "%s" size = 15>
<p><b>how many friends do you have?</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,20,30,40):
        checked = ''
        if i == howmany:
            checked = 'CHECKED'
        friends.append(fradio % (str(i),checked,str(i)))
    print('%s%s' % (header,formhtml % (who,url,who,''.join(friends))))    #join函数使得friends中每个元素以''连接

reshtml = '''<html><head><tltle>
Friends CGI demon</title></head>
<body><h3>Friends list for:<i>%s</i></h3>
your name is: <b>%s</b><p>
you have <b>%s</b> friends.
<p>Click <a href = "%s">here</a> to edit info again
</body></html>
'''

def doresult(who,howmany):
    newurl = url + '?action=reedit&person=%s&howmany=%s' % (urllib.parse.quote_plus(who),howmany)
    print(header + reshtml % (who,who,howmany,newurl))

def process():
    err = ''
    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':
            err = 'please select number of friends'
        else:
            howmany = 0

    if not err:
        if 'action' in form and form['action'].value != 'reedit':
            doresult(who,howmany)
        else:
            showForm(who,howmany)
    else:
        showErr(err)

if __name__ == '__main__':
    process()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章