通讀Python官方文件之cgi

2021-09-14 05:03:22 字數 4563 閱讀 6123

閘道器協議學習:cgi、fastcgi、wsgi

簡單點說:

cgi指令碼由http伺服器啟動,通常用來處理使用者通過提交的資料。

通常,cgi指令碼位於伺服器的專門的cgi-bin目錄下。http伺服器在指令碼的shell環境中放置了請求相關的資訊,比如客戶端的hostname,請求的url,請求的字串以及其他東西。伺服器執行指令碼,並把輸出返回給客戶端。

指令碼的輸入也和客戶端相連,有時表單資料是通過這種方式讀取的。其他時候,表單資料是通過urlquery字串傳遞的。這個模組用於處理不同的情況,提供乙個簡單的介面。同時提供了一些功能,幫助除錯指令碼。最近新增的功能是通過表單上傳檔案。

cgi指令碼的輸出由兩部分組成,由乙個空行分割。第一部分包含一些頭部,告訴客戶接下來返回的是什麼資料。大概是這樣:

print("content-type: text/html")    # 接下來返回的是html

print() # 空白行,頭部結束

第二部分,一般來說是html。客戶端軟體可以展示這些頁面,什麼的。

當你寫乙個新的指令碼時,新增下面這兩行:

import cgitb

cigtb.enable()

這將會啟用乙個異常處理器,如果發生了錯誤,它就會把錯誤返回給瀏覽器。如果你不想讓使用者看到,也可以指定輸出目錄。

import cgitb

cgitb.enable(display=0, logdir='/path/to/logdir')

補充:

post請求提交資料有兩種方式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)方法會返回所有keykey_name的值。

如果上傳的表單中存在檔案,你可以呼叫read()函式或者readline()函式。

前面介紹了,如果使用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.parsecgi.parse_qscgi.parse_qsl,已經被移植到urllib.parsecgi.escape被移植到html.escape

原則:如果你啟動了乙個外部程式函式,永遠不要把使用者的輸入直接傳入shell。即使要傳入也要確保只含有字母和數字、橫槓、下劃線和點。

閱讀你的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.py安裝到你的cgi指令碼目錄下,啟動這個指令碼,他就會將它的環境和內容以html的格式輸出。給他乙個合適的模式,傳送給他乙個請求。如果它被安裝在cgi-bin目錄下,在你的瀏覽器內輸入如下url:

http://yourhostname/cgi-bin/c...\
如果返回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會可讀。

官方文件之Cookie

蘋果文件翻譯內容 由於http協議的無狀態性,客戶端通常使用的持久化儲存資料都是來自於攜帶cookies的url網路請求 系統缺省會每次在傳送網路請求的時候在請求頭裡面設定cookie,我們通常沒有管理他,通過charles軟體抓包可以明顯的看到請求頭裡面多了個set cookie 引數 url l...

python官方 Python官方中文文件強勢來襲

python 官方支援的文件一直沒有中文。小夥伴們已經習慣了原汁原味的英文文件,但如果有官方中文文件,對於初學者來說,門檻會大大的降低。現在中文文件強勢來襲 以前也是有一些第三方維護的 python 中文文件,不過可能因為人力等限制,並做不到同步更新與維護。目前也有很多高質量的 python 中文資...

DRF官方文件之Response

responses rest framework提供了乙個response類來根據客戶端的請求方式返回不同型別的資料。response類繼承自django的 templateresponse。response物件會初始化python格式的資料。rest framework使用標準的http協議內容決...