開發5分鐘,除錯2小時 - 該如何debug?

Crossin先生發表於2018-09-29

幾年來我在答疑群、論壇、公眾號、知乎回答的各種問題,沒有一萬也有八千。其中有三分之二以上都是在幫人看報錯,幫人 debug(除錯程式碼)

可以說,會不會 debug,有沒有 debug 的意識,懂不懂 debug 的技巧,是有沒有入門程式設計的重要標誌。然而絕大多數的程式設計書籍和課程都不會強調這點。教的人和學的人都只關注明面上的知識點,卻往往忽略了學習的本質在於“授之以漁”。

在我們的碼上行動基礎課程裡,《如何 debug》是必須掌握的一個章節。後來發現不少有基礎的同學直接參與爬蟲課程,但同樣缺失 debug 的基本功,於是我又把 debug 作為前序章節加入到爬蟲課程裡。

為什麼很多初學者會覺得程式設計論壇裡的人都不大友好?我經常對提問者說:你這個問題我無法回答,因為你缺少最基本的除錯資訊。而如果你把除錯資訊提供到位了,基本也就不需要我回答了。歸根結底,是從來沒有人告訴過初學者,你得先除錯。大部分人都是碰了很多次壁最後終於明白,啊多麼痛的領悟!

今天我就從 debug 課程裡挑選最關鍵的幾點講一下。不要光 mark,現在就看一遍,嫌長就看加粗高亮部分。以後開發中再遇到問題,按照以下要點自查。

1. 選一個好的 IDE

初學者一半以上的問題是低階錯誤,比如縮排錯誤(空格、tab混用)、變數前後命名不一致(拼寫錯誤)、函式呼叫時傳遞的引數不對、少引號括號、用了中文全形等等。這些人眼很難一下發現的錯誤,程式碼編輯器可以在寫程式碼的時候就給你提示出來。

開發5分鐘,除錯2小時 - 該如何debug?

如圖中,分別有一個函式名寫錯了、一個變數名拼錯了,還有一個 if 前面的空格我用了 Tab 鍵而不是 4 個空格。Pycharm 在你寫程式碼時就會給出高亮或者波浪線的提示,把滑鼠移上去還可以看到錯誤的提示。否則這些錯誤是很難被發現的。

另外,IDE 的一個重要功能就是可以自動補全程式碼,省事而且不容易出錯。

Python 自帶的 IDLE 在這方面做得並不好,剛起步時可以用用,上手後儘快轉。個人推薦用 Pycharm,即使是功能相對較少的免費社群版本,也足夠應付開發時需求。VSCode 也是很好的選擇之前有過兩篇介紹文章,公眾號裡回覆 pycharm 可檢視

2. 學會看報錯資訊

絕大多數問題不是直接在程式碼層面就出現的,而是執行時才發生。這時候正常都會導致程式中斷並輸出報錯資訊。一般從報錯資訊裡就可以看出報錯的位置和原因

開發5分鐘,除錯2小時 - 該如何debug?

很多初學者怕看報錯資訊,這不行。即使英語不好,也嘗試著去看,套路就那麼些,看幾次你就大概熟悉了,但對你除錯的幫助非常大。

不過有時報錯顯示的位置是有問題的,這種情況通常的原因都是前面某一行的括號或者引號有問題,而導致後面的程式碼錯亂。所以如果報錯指出的位置看不出問題,試著往前看一看

在程式碼中使用 try...except 可以避免程式因異常中斷。但在開發時不要使用異常處理,否則阻止了報錯資訊的發出,影響除錯。

報錯資訊還有個用處就是直接複製到搜尋引擎裡進行搜尋,而這方面 Google 的結果比百度要好,英文網站要比中文網站好。(怎樣用 Google 這個話題不便在此公開討論。)

開發5分鐘,除錯2小時 - 該如何debug?

3. 別捨不得用 print

這一點是最重要的!

在程式中輸出並分析 log(日誌)是一種很基本但卻很靈活很有效的除錯方式。使用 print 就是 log 的最常用方法。

log 的作用主要是:

a. 確定程式的執行路徑。一個函式有沒有被呼叫,一個 if 塊有沒有被執行,一個 while 迴圈執行了幾次,到了哪一步中斷了,都可以通過 print 出相關資訊來檢視。

b. 檢視變數的狀態。程式自身的報錯會告訴你發生了什麼錯誤,但你還需要找出為什麼會發生錯誤。通過 print 輸出出錯語句涉及到的相關變數的值和型別,可以幫助分析出錯原因。

c. 找出出錯位置。往往錯誤的原因並不在報錯的位置,所以多輸出一些標記,多 print 不同位置的變數值,檢視變數在執行過程中值的變化情況,可以觀察是在哪裡發生了問題。

幾個通過 log 除錯的經驗技巧:

a. 多輸出一些輔助資訊,方便自己檢視,不然一堆資料看花眼。比如我一般輸出時會標註上變數名,再輸出變數型別,以及變數的值。比如:

開發5分鐘,除錯2小時 - 該如何debug?

b. 在出錯行之前輸出。報錯行涉及的一些變數,他們的數值和型別,全都輸出出來,看看和預期是否一致。

c. 一行做一件事。如果你出錯的一行裡連續呼叫了多個函式或運算,請分開寫,分開輸出。

d. 對於字串,直接 print 會被轉義和解碼,影響對變數實際值的觀察。可以用 print(repr(text)) 或 print([text]) 的方式檢視。

e. 對於編碼問題,用好 type 方法和 chardet 庫輔助判斷。這點之前編碼相關的文章裡有說明,公眾號裡回覆 pycharm 可檢視

f. 為了方便記錄和回溯問題日誌,通常也會將 log 輸出到檔案。也有專門的 logging 模組做這事。

記住:print 不要錢,能用多少是多少!確保你清楚程式執行的狀態細節。

4. 斷點除錯

斷點除錯看參考之前文章 如何在 Python 中使用斷點除錯,這裡不再複述。


前面這些基本是操作層面的具體 debug 方法,下面我再來談點 debug 的思想和原則

1. 縮小出錯的範圍

軟體開發中有一個“單元測試”的概念:如果你寫了一個函式,應該先執行下這個函式是不是正常,各種引數下會不會出現錯誤。這樣可以把問題控制在較小的範圍內解決。

2. 控制變數法 + 二分查詢法

比如做爬蟲沒有抓到正確資料,那麼到底是 (1)請求來的數值不對,還是 (2)文字處理方法不對?如果你認為是文字處理方法沒有問題,就手動給定一個正確格式的字串文字,應該可以得到正確的結果。這就相當於控制了因素(2),只改變因素(1),根據執行結果就可以確認或排除問題的所在

二分查詢法是一個定位問題的技巧。如果你的程式碼裡有問題,那麼問題要麼在前半段,要麼在後半段。你先把後半段程式碼去掉執行,看看程式是否還報錯,就知道錯誤在哪部分。依次類推,不斷折半,直到找到引發報錯的程式碼

3. 先重現,再解決,最後驗證

有的錯誤不是每次出現。這時候最好別急著去改程式碼,而是想辦法可以穩定重現問題。當你能順利重現問題的時候,通常離分析解決它也不遠了。解決了之後,再按照之前重現的方式驗證修改是否確實有效。

4. 想清楚再動手

不論是開發程式碼,還是除錯 debug,在做一個動作前要清楚自己的目的是什麼,而不是盲目地進行改動。不要猜!我經常會看見一些新手遇到問題之後,反覆執行程式碼,或者不斷調整引數,妄想某次執行程式就能神奇地通過了。這是一個很不好的態度,請避免。要恪守邏輯,知道現在要解決的問題是什麼,需要得到那些資訊,可能的假設是什麼,如何通過修改程式碼去驗證你的判斷,這樣才是合理的 debug 方式。


以上就是一些 debug 的基本思想和技巧。這裡僅僅是概要精華,操作起來遠不止這麼多,同時還需要實際的練習才能掌握。我能做的就是給你的程式設計技能樹下埋一顆種子,能不能生根發芽,就看各位自己的澆灌了。(我相信,即使我這裡都說過了,還是會有很多人依舊犯上述提及的錯誤 ╮(╯_╰)╭ 隨緣吧,師傅領進門,修行在個人……)

想要深入瞭解更多程式設計的思想和技巧,歡迎來我們的碼上行動知識星球


下課!


════

其他文章及回答:

如何自學Python | 新手引導 | 精選Python問答 | Python單詞表 | 知乎下載器 | 人工智慧 | 嘻哈 | 爬蟲 | 我用Python | 高考 | requests | AI平臺

歡迎搜尋及關注:Crossin的程式設計教室

開發5分鐘,除錯2小時 - 該如何debug?

相關文章