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()

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