前面幾小節(jié)介紹了調(diào)試 Python 程序如何調(diào)置斷點、如何啟動一個調(diào)試器,以及查看變量值等功能。本節(jié)將以完整的例子調(diào)試一些代碼,串講一下調(diào)試過程中經(jīng)常用到的主要功能。
1. 準備一個例子
下面例子是通過并發(fā)的方式從有道的網(wǎng)站獲取多個英語單詞的解釋, 將以下代碼復制到項目中的文件中, 比如創(chuàng)建一個文件 debug_demo.py
import requests
import re
from concurrent.futures import ThreadPoolExecutor
import time
def download_html(word):
time.sleep(5)
output = []
headers = {
'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) '
'Chrome / 72.0.3626.121Safari / 537.36'
}
url = 'http://dict.youdao.com/w/eng/{}/'.format(word)
try:
r = requests.get(url, headers=headers)
if r.status_code == 200:
pattern = re.compile(' <span class="keyword">(.*?)</span>.*?<span class="pronounce">(.*?)\n.'
'*?<span class="phonetic">(.*?)</span>.*?<span class="pronounce">(.*?)\n.*?'
'<span class="phonetic">(.*?)</span>.*?<div class="trans-container">.*?<ul>.*?'
'<li>(.*?)</li>.*?<li>(.*?)</li>', re.S)
word = re.findall(pattern, r.text)
print(word)
output.append(word)
except Exception as e:
pass
return output
if __name__ == '__main__':
text = input("請輸入要查詢的單詞,中間用逗號隔開:")
start = time.time()
words = text.split(',')
pool = ThreadPoolExecutor(4)
threads = [pool.submit(download_html, word) for word in words]
for i in threads:
print(i.result)
end = time.time()
print(end - start)
2. 設(shè)置斷點
在調(diào)試之前通常需要設(shè)置斷點,斷點可以設(shè)置在循環(huán)或者條件判斷的表達式處或者程序的關(guān)鍵點。最為直接的方法是雙擊代碼編輯處左側(cè)邊緣,可以看到出現(xiàn)紅色的小圓點。
3. 啟動調(diào)試器
PyCharm 允許以多種方式啟動調(diào)試器會話。我們選擇在編輯器點擊右鍵, 在上下文菜單選擇 Debug ‘debug_demo’。
調(diào)試器啟動,顯示 Debug 工具窗口的 Consoel 選項卡,要求輸入想查詢的單詞:
按要求輸入單詞后回車,然后調(diào)試器在第一個斷點掛起程序,尚未執(zhí)行帶斷點的行變?yōu)樗{色:
4. 單步調(diào)試
如果使用步進工具欄按鈕 Step over,將移動到下一行。如果單擊 Step into 按鈕,您將看到在行 ThreadPoolExecutor(3) 進入文件 thread.py, 在 thread.py 中可繼續(xù)單擊 Step over 進入下一步,然后單擊 Step out 回到主程序。除此以外,可以點擊 Debug 工具欄上的 Rusume Program (F9), 會直接移到下一個斷點。
Tips: 如果要專注于自己的代碼,請使用 Step into my code 單步執(zhí)行 按鈕, 可避免進入系統(tǒng)庫類。
5. 查看變量
可以在 Debug 工具欄中的 Variable 查看變量,如果要動態(tài)的監(jiān)測某個變量可以把變量加到 Watches 欄中。當調(diào)試進行到該變量所在的語句時,在該窗口中可以直接看到該變量的具體值。
在 Watches 選項卡中點擊 + 按鈕,然后鍵入要監(jiān)測的變量的名稱,代碼自動補全是可用的。
Tips:如果 Watches 選項卡沒顯示,只需單擊 Variable 選項卡工具欄上的 Show watches in varaibles tab。
可能會看到一個錯誤,這意味著變量尚未定義:
‘’
但是,當程序執(zhí)行繼續(xù)到定義變量的范圍時,就會獲取到相應(yīng)的值:
6. 子線程調(diào)試
上面的例子是多線程程序,使用 ThreadPoolExecutor 同時起 3 個線程, submit() 提交任務(wù)到線程池不是阻塞的,而是立即返回。當主線程啟動了子線程后,會在多線程窗口看到系統(tǒng)自動創(chuàng)建的線程名。
當調(diào)試進入到各個線程的子程序時,F(xiàn)rame 會自動切換到其所對應(yīng)的 frame,相應(yīng)的變量欄中也會顯示與該過程對應(yīng)的相關(guān)變量, 使用 setp in,step over 便可以在各自的子線程進行調(diào)試了。
7. 計算表達式
我們隨時可以計算任何表達式, 單擊"Evaluate Expression…“按鈕,然后在打開的對話框中輸入表達式,然后單擊"Evaluate”。
8. 小結(jié)
本節(jié)例子基本覆蓋了 Python 調(diào)試過程中涉及的一些主要功能,更多細節(jié)還需要在不斷實踐中逐漸加深體會與理解,最終可以高效的調(diào)試代碼與解決遇到的問題。