Python實(shí)現(xiàn)Web請(qǐng)求與響應(yīng)的教學(xué)指南
一、Web 請(qǐng)求與響應(yīng)基礎(chǔ)
(一)Web 請(qǐng)求與響應(yīng)的定義與組成
Web 請(qǐng)求與響應(yīng)是 Web 通信的基礎(chǔ),其中 Web 請(qǐng)求由客戶端發(fā)起,服務(wù)器處理后返回響應(yīng)。
1.Web 請(qǐng)求的組成
請(qǐng)求行:包含請(qǐng)求方法(如 GET、POST、PUT、DELETE 等)、URL 以及 HTTP 協(xié)議版本(如 HTTP/1.1)。例如,一個(gè) GET 請(qǐng)求的請(qǐng)求行可能是 “GET /index.html HTTP/1.1”。
請(qǐng)求頭:包含關(guān)于客戶端信息、請(qǐng)求體類型、瀏覽器類型等元數(shù)據(jù)。常見(jiàn)的請(qǐng)求頭有 User - Agent(用于標(biāo)識(shí)客戶端類型)、Content - Type(表示請(qǐng)求體的數(shù)據(jù)類型)等。
請(qǐng)求體:在 POST 請(qǐng)求中通常包含用戶提交的數(shù)據(jù),如表單數(shù)據(jù)或文件等,而 GET 請(qǐng)求一般沒(méi)有請(qǐng)求體。
2.Web 響應(yīng)的組成
- 響應(yīng)行:包括 HTTP 協(xié)議版本、狀態(tài)碼和狀態(tài)消息。例如 “HTTP/1.1 200 OK”,其中 200 是狀態(tài)碼,OK 是狀態(tài)消息。
- 響應(yīng)頭:包含關(guān)于響應(yīng)的信息,如內(nèi)容類型(Content - Type)、服務(wù)器信息(Server)等。
- 響應(yīng)體:包含實(shí)際返回的數(shù)據(jù),可能是 HTML 頁(yè)面、JSON 數(shù)據(jù)等。
(二)HTTP 協(xié)議概述
HTTP(Hypertext Transfer Protocol)是 Web 上傳輸數(shù)據(jù)的協(xié)議,負(fù)責(zé)瀏覽器與服務(wù)器之間的通信。以下是常見(jiàn)的 HTTP 方法:
GET:請(qǐng)求服務(wù)器獲取資源,通常用于讀取數(shù)據(jù),其特點(diǎn)是請(qǐng)求參數(shù)會(huì)附加在 URL 后面,以 “?” 分隔,多個(gè)參數(shù)用 “&” 連接。例如 “https://example.com/search?keyword=python”
。
POST:提交數(shù)據(jù)到服務(wù)器,通常用于表單提交、文件上傳等,數(shù)據(jù)通過(guò)請(qǐng)求體傳輸,不會(huì)顯示在 URL 中,相對(duì)更安全。
PUT:用于更新服務(wù)器上的資源。
DELETE:用于刪除服務(wù)器上的資源。
(三)常見(jiàn)的 HTTP 狀態(tài)碼
- 200 OK:表示請(qǐng)求成功,服務(wù)器返回所請(qǐng)求的數(shù)據(jù)。
- 301 Moved Permanently:表示資源已永久移動(dòng),客戶端會(huì)自動(dòng)重定向到新的 URL。
- 404 Not Found:表示請(qǐng)求的資源不存在。
- 500 Internal Server Error:表示服務(wù)器內(nèi)部錯(cuò)誤。
二、Python 的 requests 庫(kù)
(一)安裝 requests 庫(kù)
在使用 requests 庫(kù)之前,需要先進(jìn)行安裝。如果你的系統(tǒng)中已經(jīng)安裝了 Python 的包管理工具 pip,可以通過(guò)以下命令在命令行中安裝:
pip install requests
(二)發(fā)送 GET 請(qǐng)求
GET 請(qǐng)求通常用于獲取數(shù)據(jù),我們可以通過(guò) requests.get () 方法來(lái)發(fā)送 GET 請(qǐng)求,并處理返回的響應(yīng)。以下是一個(gè)簡(jiǎn)單的示例代碼:
import requests # 發(fā)送GET請(qǐng)求 response = requests.get("https://www.example.com") # 輸出響應(yīng)的狀態(tài)碼 print("Status Code:", response.status_code) # 輸出響應(yīng)的內(nèi)容 print("Response Body:", response.text) # 輸出響應(yīng)頭 print("Response Headers:", response.headers) # 獲取響應(yīng)內(nèi)容的長(zhǎng)度 print("Content Length:", len(response.text))
代碼解釋:
- requests.get()用于發(fā)送 GET 請(qǐng)求,括號(hào)內(nèi)傳入要請(qǐng)求的 URL,該方法會(huì)返回一個(gè) Response 對(duì)象,包含了服務(wù)器返回的所有信息。
- response.status_code用于獲取 HTTP 響應(yīng)狀態(tài)碼,通過(guò)該狀態(tài)碼可以判斷請(qǐng)求是否成功。
- response.text用于獲取響應(yīng)的正文內(nèi)容,通常是 HTML 或 JSON 數(shù)據(jù),返回的是字符串類型。
- response.headers用于獲取響應(yīng)頭,它是一個(gè)類似字典的對(duì)象,可以通過(guò)鍵來(lái)訪問(wèn)相應(yīng)的值。
- len(response.text)用于返回響應(yīng)正文的長(zhǎng)度,通過(guò)該值可以幫助我們了解返回內(nèi)容的大小。
(三)發(fā)送 POST 請(qǐng)求
POST 請(qǐng)求用于將數(shù)據(jù)提交到服務(wù)器,通常用于表單提交或上傳文件等場(chǎng)景,我們使用 requests.post () 方法來(lái)發(fā)送 POST 請(qǐng)求。以下是示例代碼:
import requests # 發(fā)送POST請(qǐng)求 url = "https://httpbin.org/post" data = {"name": "Alice", "age": 25} response = requests.post(url, data=data) # 輸出響應(yīng)狀態(tài)碼 print("Status Code:", response.status_code) # 輸出響應(yīng)內(nèi)容(JSON格式) print("Response Body:", response.json())
代碼解釋:
- requests.post()用于發(fā)送 POST 請(qǐng)求,第一個(gè)參數(shù)是 URL,第二個(gè)參數(shù) data 是一個(gè)字典,包含了要提交的數(shù)據(jù)。requests 庫(kù)會(huì)自動(dòng)將其編碼為application/x-www-form-urlencoded格式。
- response.json()用于解析返回的 JSON 數(shù)據(jù),它會(huì)將 JSON 格式的響應(yīng)內(nèi)容轉(zhuǎn)換為 Python 的字典或列表等數(shù)據(jù)結(jié)構(gòu),方便我們進(jìn)行處理。
(四)處理響應(yīng)頭和狀態(tài)碼
響應(yīng)頭提供了關(guān)于服務(wù)器的信息,狀態(tài)碼則告訴我們請(qǐng)求是否成功。我們可以通過(guò)以下代碼來(lái)獲取響應(yīng)頭和狀態(tài)碼:
import requests # 發(fā)送GET請(qǐng)求 response = requests.get("https://www.example.com") # 獲取響應(yīng)頭 print("Response Headers:", response.headers) # 獲取響應(yīng)狀態(tài)碼 print("Status Code:", response.status_code) # 獲取內(nèi)容類型 print("Content - Type:", response.headers.get("Content - Type"))
代碼解釋:
response.headers返回響應(yīng)頭,其中包含了如 Content - Type、Date、Server 等信息,我們可以通過(guò)字典的 get () 方法來(lái)獲取指定鍵的值,如獲取內(nèi)容類型。
response.status_code返回 HTTP 狀態(tài)碼,通過(guò)判斷該狀態(tài)碼是否為 200 等成功狀態(tài)碼,可以確定請(qǐng)求是否成功執(zhí)行。
(五)發(fā)送帶查詢參數(shù)的 GET 請(qǐng)求
在 GET 請(qǐng)求中,我們可以通過(guò) URL 傳遞查詢參數(shù)。例如,訪問(wèn)一個(gè)包含參數(shù)的 URL,我們可以通過(guò) requests.get () 方法的 params 參數(shù)來(lái)傳遞查詢參數(shù)。以下是示例代碼:
import requests # 發(fā)送帶查詢參數(shù)的GET請(qǐng)求 url = "https://httpbin.org/get" params = {"name": "Alice", "age": 25} response = requests.get(url, params=params) # 輸出響應(yīng)內(nèi)容 print("Response Body:", response.json())
代碼解釋:
params是一個(gè)字典,包含了要傳遞的查詢參數(shù)。requests.get () 方法會(huì)自動(dòng)將這些參數(shù)編碼到 URL 中,生成的 URL 類似于 “https://httpbin.org/get?name=Alice&age=25”。
(六)發(fā)送帶表單數(shù)據(jù)的 POST 請(qǐng)求
POST 請(qǐng)求可以用來(lái)提交表單數(shù)據(jù),以下是使用 requests 發(fā)送帶表單數(shù)據(jù)的 POST 請(qǐng)求的示例代碼:
import requests # 發(fā)送帶表單數(shù)據(jù)的POST請(qǐng)求 url = "https://httpbin.org/post" data = {"username": "testuser", "password": "mypassword"} response = requests.post(url, data=data) # 輸出響應(yīng)的內(nèi)容 print("Response Body:", response.json())
代碼解釋:
data參數(shù)是一個(gè)字典,包含了表單提交的數(shù)據(jù),requests 庫(kù)會(huì)自動(dòng)將數(shù)據(jù)編碼為application/x-www-form-urlencoded格式,該格式是表單數(shù)據(jù)提交的常見(jiàn)格式。
三、處理 JSON 響應(yīng)
許多 Web API 返回的數(shù)據(jù)格式是 JSON,Python 的 requests 庫(kù)提供了方便的 JSON 處理方法。以下是示例代碼:
import requests # 發(fā)送GET請(qǐng)求并獲取JSON響應(yīng) url = "https://api.github.com/users/octocat" response = requests.get(url) # 解析JSON數(shù)據(jù) data = response.json() # 輸出用戶的GitHub信息 print("User Login:", data["login"]) print("User Name:", data["name"])
代碼解釋:
response.json()方法會(huì)將響應(yīng)的內(nèi)容解析為 Python 字典,這樣我們就可以像操作普通字典一樣方便地處理 JSON 數(shù)據(jù),通過(guò)鍵來(lái)獲取相應(yīng)的值。
四、文件操作
(一)打開(kāi)文件的模式
Python 使用內(nèi)置的 open () 函數(shù)來(lái)打開(kāi)文件,打開(kāi)文件時(shí)需要指定文件模式(即操作文件的方式)。以下是常見(jiàn)的文件打開(kāi)模式:
- 只讀模式(r):默認(rèn)模式,文件必須存在。如果文件不存在,會(huì)拋出 FileNotFoundError 異常。
- 寫入模式(w):如果文件存在,會(huì)覆蓋文件內(nèi)容;如果文件不存在,會(huì)創(chuàng)建新文件。
- 追加模式(a):如果文件存在,寫入的數(shù)據(jù)會(huì)追加到文件末尾;如果文件不存在,會(huì)創(chuàng)建新文件。
- 獨(dú)占創(chuàng)建模式(x):若文件已存在,操作會(huì)失敗并拋出 FileExistsError 異常,此模式通常用于創(chuàng)建文件時(shí)防止覆蓋現(xiàn)有文件。
- 二進(jìn)制讀取模式(rb):用于讀取非文本文件(如圖片、音頻文件)。
- 二進(jìn)制寫入模式(wb):用于寫入非文本文件。
- 讀寫模式(+):文件必須存在,既可以讀取文件內(nèi)容,也可以寫入數(shù)據(jù)。
- w + 模式:讀寫模式,如果文件存在,會(huì)覆蓋文件內(nèi)容;如果文件不存在,會(huì)創(chuàng)建新文件。
- a + 模式:讀寫模式,文件存在時(shí),數(shù)據(jù)會(huì)追加到文件末尾;如果文件不存在,會(huì)創(chuàng)建新文件。
- rb + 模式:二進(jìn)制讀寫模式。
以下是使用不同模式打開(kāi)文件的示例代碼:
# 以只讀模式打開(kāi)文件 with open('example.txt', 'r') as file: content = file.read() print(content) # 以寫入模式打開(kāi)文件,文件內(nèi)容會(huì)被覆蓋 with open('example.txt', 'w') as file: file.write("這是新的文件內(nèi)容。\n") # 以追加模式打開(kāi)文件,新的內(nèi)容會(huì)追加到文件末尾 with open('example.txt', 'a') as file: file.write("追加的內(nèi)容。\n") # 以二進(jìn)制模式打開(kāi)文件(例如讀取圖片) with open('image.jpg', 'rb') as file: binary_data = file.read() print("讀取到的二進(jìn)制數(shù)據(jù):", binary_data[:20])
(二)讀取文件
Python 中的文件讀取功能非常強(qiáng)大,以下是幾種常見(jiàn)的讀取方式:
read () 方法:用于讀取文件中的所有內(nèi)容,讀取后的內(nèi)容會(huì)作為字符串返回。示例代碼如下:
with open('example.txt', 'r') as file: content = file.read() print(content)
readline () 方法:每次讀取一行文件內(nèi)容,適用于需要逐行處理文件的情況。示例代碼如下:
with open('example.txt', 'r') as file: line = file.readline() while line: print(line.strip()) # strip()用來(lái)去除行末的換行符 line = file.readline()
readlines () 方法:會(huì)一次性讀取文件中的所有行,并將每行數(shù)據(jù)存儲(chǔ)為一個(gè)列表的元素,適用于需要讀取整個(gè)文件并進(jìn)行行處理的情況。示例代碼如下:
with open('example.txt', 'r') as file: lines = file.readlines() for line in lines: print(line.strip())
(三)寫入文件
Python 提供了幾種方法將數(shù)據(jù)寫入文件,寫入操作常用于日志記錄、數(shù)據(jù)導(dǎo)出等場(chǎng)景。
使用 write () 方法寫入文件:該方法將指定的字符串寫入文件。若文件以 “w” 模式打開(kāi),原文件內(nèi)容會(huì)被覆蓋;若以 “a” 模式打開(kāi),內(nèi)容會(huì)被追加到文件末尾。
示例代碼如下:
with open('output.txt', 'w') as file: file.write("這是第一行數(shù)據(jù)。\n") file.write("這是第二行數(shù)據(jù)。\n")
使用 writelines () 方法寫入多行數(shù)據(jù):該方法接受一個(gè)可迭代對(duì)象(如列表、元組等),將其元素寫入文件中,每個(gè)元素將作為一行寫入文件。示例代碼如下:
lines = ["第一行數(shù)據(jù)。\n", "第二行數(shù)據(jù)。\n", "第三行數(shù)據(jù)。\n"] with open('output.txt', 'w') as file: file.writelines(lines)
(四)下載文件示例
我們可以通過(guò) requests 庫(kù)來(lái)下載文件,并將其保存到本地。以下是下載一個(gè)圖片文件的示例代碼:
import requests url = "https://www.example.com/image.jpg" # 圖片URL response = requests.get(url) # 檢查請(qǐng)求是否成功 if response.status_code == 200: # 使用二進(jìn)制模式寫入文件 with open('downloaded_image.jpg', 'wb') as file: file.write(response.content) print("圖片下載成功!") else: print(f"下載失敗,狀態(tài)碼:{response.status_code}")
代碼解釋:
首先使用 requests.get () 方法發(fā)送 GET 請(qǐng)求獲取圖片文件的內(nèi)容,設(shè)置 URL 為圖片的地址。
通過(guò)判斷響應(yīng)的狀態(tài)碼是否為 200,來(lái)確定請(qǐng)求是否成功。
如果請(qǐng)求成功,使用 with open () 語(yǔ)句以二進(jìn)制寫入模式('wb')打開(kāi)文件,然后通過(guò) file.write (response.content) 將響應(yīng)的內(nèi)容(二進(jìn)制數(shù)據(jù))寫入文件中。response.content 返回的是字節(jié)流數(shù)據(jù),適合用于處理二進(jìn)制文件。
(五)文件操作中的注意事項(xiàng)
文件是否存在:在打開(kāi)文件時(shí),必須確保文件路徑正確。如果文件不存在,可以使用 os.path.exists () 函數(shù)檢查文件是否存在,或者使用 try - except 語(yǔ)句捕獲 FileNotFoundError 異常。示例代碼如下:
import os if os.path.exists('example.txt'): with open('example.txt', 'r') as file: content = file.read() else: print("文件不存在!")
文件權(quán)限:在操作文件時(shí),可能會(huì)遇到權(quán)限不足的問(wèn)題。例如,嘗試寫入只讀文件,或訪問(wèn)沒(méi)有讀取權(quán)限的文件。在這種情況下,可以使用 try - except 語(yǔ)句來(lái)捕獲 PermissionError 異常。示例代碼如下:
try: with open('readonly_file.txt', 'w') as file: file.write("嘗試寫入只讀文件") except PermissionError: print("權(quán)限不足,無(wú)法寫入文件。")
文件自動(dòng)關(guān)閉:使用 with open () 語(yǔ)句時(shí),Python 會(huì)自動(dòng)管理文件的打開(kāi)和關(guān)閉,無(wú)需顯式調(diào)用 file.close () 方法,這有助于避免文件未關(guān)閉的問(wèn)題,減少資源泄漏的風(fēng)險(xiǎn)。
(六)其他常用文件操作
獲取文件信息:Python 提供了 os 和 os.path 模塊,可以獲取文件的大小、修改時(shí)間等信息。示例代碼如下:
import os file_path = 'example.txt' print("文件大小:", os.path.getsize(file_path), "字節(jié)") print("文件修改時(shí)間:", os.path.getmtime(file_path))
刪除文件:使用 os.remove () 函數(shù)可以刪除文件。示例代碼如下:
import os file_path = 'example.txt' if os.path.exists(file_path): os.remove(file_path) print(f"{file_path}已刪除!") else: print("文件不存在!")
五、錯(cuò)誤處理與異常捕獲
在進(jìn)行 Web 請(qǐng)求時(shí),可能會(huì)發(fā)生各種錯(cuò)誤,例如網(wǎng)絡(luò)超時(shí)、服務(wù)器錯(cuò)誤等。requests 庫(kù)通過(guò)異常處理機(jī)制幫助我們捕獲這些錯(cuò)誤,Python 的 try 語(yǔ)句能夠捕獲和處理代碼塊中的異常,從而避免程序崩潰,并且提供了處理錯(cuò)誤的機(jī)會(huì)。
(一)try 語(yǔ)句的使用
try 語(yǔ)句用于捕獲和處理異常,它由以下三部分組成(其中 else 塊和 finally 塊可選):
- try 塊:包含可能會(huì)引發(fā)異常的代碼。當(dāng)代碼運(yùn)行過(guò)程中發(fā)生錯(cuò)誤時(shí),程序會(huì)跳到相應(yīng)的 except 塊進(jìn)行處理。
- except 塊:當(dāng) try 塊中的代碼出現(xiàn)異常時(shí),程序會(huì)跳轉(zhuǎn)到 except 塊執(zhí)行。在 except 中可以指定要捕獲的異常類型,如 Timeout、HTTPError 等。
- else 塊(可選):如果 try 塊中的代碼沒(méi)有拋出異常,則會(huì)執(zhí)行 else 塊中的代碼。
- finally 塊(可選):無(wú)論是否發(fā)生異常,finally 塊中的代碼都會(huì)執(zhí)行,通常用于清理資源(如關(guān)閉文件、數(shù)據(jù)庫(kù)連接等)。
(二)示例:捕獲常見(jiàn)異常
以下是捕獲常見(jiàn)異常的示例代碼:
import requests from requests.exceptions import RequestException, Timeout, HTTPError try: # 發(fā)送GET請(qǐng)求,并設(shè)置超時(shí)時(shí)間為5秒 response = requests.get("https://www.example.com", timeout=5) # 如果狀態(tài)碼不是200,拋出HTTPError異常 response.raise_for_status() # 如果狀態(tài)碼是4xx或5xx,拋出異常 # 如果請(qǐng)求成功,則輸出響應(yīng)內(nèi)容 print("Response Body:", response.text) # 捕獲請(qǐng)求超時(shí)異常 except Timeout: print('Request timed out') # 捕獲HTTP錯(cuò)誤(如狀態(tài)碼404、500等) except HTTPError as http_err: print(f'HTTP error occurred: {http_err}') # 捕獲其他網(wǎng)絡(luò)相關(guān)的錯(cuò)誤 except RequestException as req_err: print(f'Request error occurred: {req_err}') # 可以在finally塊中清理資源(如關(guān)閉文件或連接) finally: print("Request attempt completed.")
代碼解釋:
try 塊:首先發(fā)起 HTTP 請(qǐng)求,通過(guò) timeout=5 參數(shù)設(shè)置超時(shí)時(shí)間為 5 秒。然后使用 response.raise_for_status () 方法來(lái)檢查響應(yīng)的狀態(tài)碼,如果服務(wù)器返回了錯(cuò)誤的狀態(tài)碼(如 404、500 等,即 4xx 或 5xx 的狀態(tài)碼),該方法會(huì)拋出 HTTPError 異常。如果如果狀態(tài)碼為 200 等成功狀態(tài)碼,則執(zhí)行后續(xù)的打印響應(yīng)內(nèi)容的操作。
except 塊:
- Timeout:當(dāng)請(qǐng)求超時(shí)(超過(guò)設(shè)置的 5 秒)時(shí),程序會(huì)捕獲到 Timeout 異常,并打印 “Request timed out”,提示用戶請(qǐng)求超時(shí)。
- HTTPError:若響應(yīng)的狀態(tài)碼表明出現(xiàn) HTTP 錯(cuò)誤(例如 404 表示未找到頁(yè)面,500 表示服務(wù)器內(nèi)部錯(cuò)誤等),程序會(huì)捕獲到 HTTPError 異常,并打印相關(guān)錯(cuò)誤信息,如 “HTTP error occurred: 404 Client Error: Not Found for url: https://www.example.com”,其中包含具體的錯(cuò)誤狀態(tài)碼和錯(cuò)誤描述,方便用戶了解出錯(cuò)原因。
- RequestException:該異常是所有 requests 庫(kù)異常的基類,可以捕獲任何 requests 庫(kù)拋出的異常,例如連接問(wèn)題、DNS 解析失敗等。當(dāng)發(fā)生其他網(wǎng)絡(luò)相關(guān)錯(cuò)誤時(shí),程序會(huì)捕獲到 RequestException 異常,并打印 “Request error occurred: [具體錯(cuò)誤信息]”,讓用戶知曉發(fā)生了網(wǎng)絡(luò)請(qǐng)求相關(guān)的錯(cuò)誤。
finally 塊:其中的代碼無(wú)論是否發(fā)生異常都會(huì)被執(zhí)行,這里僅打印 “Request attempt completed.”,用于表示請(qǐng)求的結(jié)束,通常在此處可以進(jìn)行一些資源清理工作,如關(guān)閉文件、數(shù)據(jù)庫(kù)連接等,確保程序的資源得到合理釋放。
(三)異常處理總結(jié)
避免程序崩潰:異常處理機(jī)制讓我們?cè)诔绦蜻\(yùn)行中能夠捕獲到錯(cuò)誤并做出相應(yīng)處理,避免程序因?yàn)橛龅疆惓6蝗槐罎ⅲ岣吡顺绦虻姆€(wěn)定性和可靠性。
精確處理異常:通過(guò) try...except 結(jié)構(gòu),可以根據(jù)不同的異常類型進(jìn)行精確的捕獲和處理,針對(duì)不同的錯(cuò)誤情況執(zhí)行不同的處理邏輯,使程序能夠更靈活地應(yīng)對(duì)各種異常情況。例如,對(duì)于超時(shí)異常可以重新發(fā)起請(qǐng)求,對(duì)于 HTTP 錯(cuò)誤可以提示用戶檢查請(qǐng)求的 URL 是否正確等。
資源清理:finally 塊用于執(zhí)行清理工作,無(wú)論是否發(fā)生異常,都會(huì)在請(qǐng)求處理完成后執(zhí)行其中的代碼,確保資源(如文件句柄、網(wǎng)絡(luò)連接等)能夠被正確釋放,避免資源泄漏問(wèn)題的發(fā)生,這對(duì)于長(zhǎng)時(shí)間運(yùn)行的程序尤為重要。
六、try語(yǔ)句
(一) 基本語(yǔ)法與結(jié)構(gòu)
try: # 可能引發(fā)異常的代碼塊 result = 10 / 0 # 除零錯(cuò)誤 except ZeroDivisionError as e: # 捕獲特定異常并獲取錯(cuò)誤對(duì)象 print(f"錯(cuò)誤: {e}") # 輸出: division by zero else: # 僅在 try 塊無(wú)異常時(shí)執(zhí)行 print("計(jì)算成功:", result) finally: # 無(wú)論是否異常都執(zhí)行(常用于資源清理) print("執(zhí)行完畢")
(二)捕獲多種異常
1 .分別處理不同異常
try: num = int("abc") # ValueError result = 10 / num # ZeroDivisionError except ValueError: print("輸入不是有效整數(shù)") except ZeroDivisionError: print("除數(shù)不能為零")
2 .合并處理同類異常
try: file = open("nonexistent.txt") # FileNotFoundError data = json.load(file) # JSONDecodeError except (FileNotFoundError, json.JSONDecodeError) as e: print(f"文件錯(cuò)誤: {e}")
( 三)捕獲所有異常
不推薦濫用,可能掩蓋嚴(yán)重問(wèn)題:
try: # 任意代碼 except Exception as e: print(f"未知錯(cuò)誤: {e}") # 推薦記錄堆棧信息用于調(diào)試 import traceback print(traceback.format_exc())
(四)主動(dòng)拋出異常(raise)
def validate_age(age): if age < 0: raise ValueError("年齡不能為負(fù)數(shù)") return age try: validate_age(-5) except ValueError as e: print(e) # 輸出: 年齡不能為負(fù)數(shù)
(五)自定義異常
class AuthError(Exception): """自定義認(rèn)證錯(cuò)誤""" def __init__(self, message="認(rèn)證失敗"): self.message = message super().__init__(self.message) # 使用示例 try: if not user_authenticated(): raise AuthError("無(wú)效令牌") except AuthError as e: print(f"認(rèn)證異常: {e}")
(六)異常鏈(raise ... from)
保留原始異常信息,便于定位問(wèn)題:
try: data = json.loads("invalid json") except json.JSONDecodeError as e: raise RuntimeError("配置解析失敗") from e
輸出:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
json.JSONDecodeError: Expecting value...
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: 配置解析失敗
( 七)上下文管理器(with 語(yǔ)句)
替代 try-finally 進(jìn)行自動(dòng)資源管理:
try: with open("data.txt", "r") as file: content = file.read() except FileNotFoundError: print("文件不存在") # 文件會(huì)自動(dòng)關(guān)閉,無(wú)需手動(dòng)調(diào)用 file.close()
(八) 常見(jiàn)異常類型
異常類型 | 觸發(fā)場(chǎng)景 |
---|---|
ZeroDivisionError | 除零錯(cuò)誤 |
TypeError | 類型不匹配(如字符串 + 整數(shù)) |
ValueError | 值不符合預(yù)期(如 int("abc")) |
FileNotFoundError | 文件不存在 |
KeyError | 字典鍵不存在 |
IndexError | 索引越界 |
PermissionError | 權(quán)限不足 |
TimeoutError | 操作超時(shí) |
(九)最佳實(shí)踐
1 .精確捕獲異常
try: result = 10 / num except (ZeroDivisionError, TypeError) as e: print(f"計(jì)算錯(cuò)誤: {e}")
2 .使用 logging 記錄異常
import logging try: # 危險(xiǎn)操作 except Exception as e: logging.error(f"系統(tǒng)異常: {e}", exc_info=True)
3 .自定義異常分層
class AppError(Exception): """應(yīng)用基礎(chǔ)異常""" class DatabaseError(AppError): """數(shù)據(jù)庫(kù)操作異常""" class ConnectionError(DatabaseError): """連接異常"""
4 .資源清理優(yōu)先用 with
# 不推薦 file = open("data.txt") try: data = file.read() finally: file.close() # 推薦 with open("data.txt") as file: data = file.read()
(十)異常處理流程
執(zhí)行 try 塊:若有異常,跳轉(zhuǎn)到第一個(gè)匹配的 except
匹配 except:按順序檢查,找到則執(zhí)行對(duì)應(yīng)代碼塊
執(zhí)行 else:若 try 無(wú)異常
執(zhí)行 finally:無(wú)論是否異常,最終執(zhí)行
(十一) 高級(jí)用法:try-except-else-finally 組合
try: # 嘗試操作 file = open("config.json", "r") except FileNotFoundError: # 處理缺失配置 print("使用默認(rèn)配置") config = DEFAULT_CONFIG else: # 無(wú)異常時(shí)讀取配置 try: config = json.load(file) except json.JSONDecodeError: print("配置格式錯(cuò)誤,使用默認(rèn)值") config = DEFAULT_CONFIG finally: file.close() # 確保文件關(guān)閉 finally: # 應(yīng)用配置 apply_config(config)
(十二)異常與性能
異常處理本身不慢,但頻繁拋出 / 捕獲會(huì)影響性能
避免用異??刂瞥R?guī)流程(如循環(huán)讀取文件)
優(yōu)先使用條件判斷(如 if os.path.exists(file))
以上就是Python實(shí)現(xiàn)Web請(qǐng)求與響應(yīng)的教學(xué)指南的詳細(xì)內(nèi)容,更多關(guān)于Python Web請(qǐng)求與響應(yīng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python基于twisted實(shí)現(xiàn)簡(jiǎn)單的web服務(wù)器
這篇文章主要介紹了Python基于twisted實(shí)現(xiàn)簡(jiǎn)單的web服務(wù)器,可模擬出簡(jiǎn)單的web服務(wù)器功能,是很實(shí)用的技巧,需要的朋友可以參考下2014-09-09Python實(shí)現(xiàn)的序列化和反序列化二叉樹(shù)算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的序列化和反序列化二叉樹(shù)算法,結(jié)合實(shí)例形式分析了Python二叉樹(shù)的構(gòu)造、遍歷、序列化、反序列化等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03python利用 pytesseract快速識(shí)別提取圖片中的文字((圖片識(shí)別)
本文介紹了tesseract的python調(diào)用,也就是pytesseract庫(kù),其中還有一些其他的內(nèi)容并沒(méi)有涉及,僅涉及到了圖片提取文字,如果你對(duì)其感興趣,可以深入探索一下,也希望能和我探討一下2022-11-11python讀取pdf格式文檔的實(shí)現(xiàn)代碼
這篇文章主要給大家介紹了關(guān)于python讀取pdf格式文檔的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04使用python寫的opencv實(shí)時(shí)監(jiān)測(cè)和解析二維碼和條形碼
這篇文章主要介紹了使用python寫的opencv實(shí)時(shí)監(jiān)測(cè)和解析二維碼和條形碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08Python3之不使用第三方變量,實(shí)現(xiàn)交換兩個(gè)變量的值
今天小編就為大家分享一篇Python3之不使用第三方變量,實(shí)現(xiàn)交換兩個(gè)變量的值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06Python Web程序部署到Ubuntu服務(wù)器上的方法
在本文記錄了我在Ubuntu中部署Flask Web站點(diǎn)的過(guò)程, 其中包括用戶創(chuàng)建、代碼獲取、Python3環(huán)境的安裝、虛擬環(huán)境設(shè)置、uWSGI啟動(dòng)程序設(shè)置,并將Nginx作為前端反向代理,需要的朋友參考下吧2018-02-02termux中matplotlib無(wú)法顯示中文問(wèn)題的解決方法
這篇文章主要介紹了termux中matplotlib無(wú)法顯示中文問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01