幾年來我在答疑羣、論壇、公衆號、知乎回答的各類問題,沒有一萬也有八千。其中有三分之二以上都是在幫人看報錯,幫人 debug(調試代碼) 。編程
能夠說, 會不會 debug,有沒有 debug 的意識,懂不懂 debug 的技巧,是有沒有入門編程的重要標誌 。然而絕大多數的編程書籍和課程都不會強調這點。教的人和學的人都只關注明面上的知識點,卻每每忽略了學習的本質在於「授之以漁」。編輯器
在咱們的 碼上行動基礎課程 裏,《 如何 debug 》是必須掌握的一個章節。後來發現很多有基礎的同窗直接參與 爬蟲課程 ,但一樣缺失 debug 的基本功,因而我又把 debug 做爲前序章節加入到爬蟲課程裏。函數
爲何不少初學者會以爲編程論壇裏的人都不大友好?我常常對提問者說:你這個問題我沒法回答,由於你 缺乏最基本的調試信息 。而若是你把調試信息提供到位了,基本也就不須要我回答了。歸根結底,是歷來沒有人告訴過初學者, 你得先調試 。大部分人都是碰了不少次壁最後終於明白,啊多麼痛的領悟!單元測試
今天我就從 debug 課程裏挑選最關鍵的幾點講一下。不要光 mark,如今就看一遍, 嫌長就看加粗高亮部分 。之後開發中再遇到問題,按照如下要點自查。學習
初學者一半以上的問題是 低級錯誤 ,好比 縮進錯誤(空格、tab混用)、變量先後命名不一致(拼寫錯誤)、函數調用時傳遞的參數不對、少引號括號、用了中文全角 等等。這些人眼很難一下發現的錯誤,代碼編輯器能夠在寫代碼的時候就給你提示出來。測試
如圖中,分別有一個函數名寫錯了、一個變量名拼錯了,還有一個 if 前面的空格我用了 Tab 鍵而不是 4 個空格。Pycharm 在你寫代碼時就會給出高亮或者波浪線的提示,把鼠標移上去還能夠看到錯誤的提示。不然這些錯誤是很難被發現的。網站
另外,IDE 的一個重要功能就是能夠 自動補全代碼 ,省事並且不容易出錯。搜索引擎
Python 自帶的 IDLE 在這方面作得並很差,剛起步時能夠用用,上手後儘快轉。 我的推薦用 Pycharm ,即便是功能相對較少的 免費社區版本 ,也足夠應付開發時需求。 VSCode 也是很好的選擇 。 以前有過兩篇介紹文章, 公衆號裏回覆 pycharm 可查看 。編碼
絕大多數問題不是直接在代碼層面就出現的,而是 運行時才發生 。這時候正常都會致使 程序中斷並輸出報錯信息 。通常從報錯信息裏就能夠看出 報錯的位置和緣由 。人工智能
不少初學者怕看報錯信息,這不行。即便英語很差,也嘗試着去看,套路就那麼些,看幾回你就大概熟悉了,但對你調試的幫助很是大。
不過有時報錯顯示的位置是有問題的,這種狀況一般的緣由都是前面某一行的括號或者引號有問題,而致使後面的代碼錯亂。因此 若是報錯指出的位置看不出問題,試着往前看一看 。
在代碼中使用 try...except 能夠避免程序因異常中斷。但在 開發時不要使用異常處理 ,不然阻止了報錯信息的發出,影響調試。
報錯信息還有個用處就是 直接複製到搜索引擎裏進行搜索 ,而這方面 Google 的結果比百度要好,英文網站要比中文網站好。(怎樣用 Google 這個話題不便在此公開討論。)
這一點是最重要的!
在程序中輸出並分析 log(日誌)是一種很基本但卻很靈活頗有效的調試方式。使用 print 就是 log 的最經常使用方法。
log 的做用主要是:
a. 肯定程序的運行路徑。 一個函數有沒有被調用,一個 if 塊有沒有被執行,一個 while 循環執行了幾回,到了哪一步中斷了,均可以經過 print 出相關信息來查看。
b. 查看變量的狀態。 程序自身的報錯會告訴你發生了什麼錯誤,但你還須要找出爲何會發生錯誤。 經過 print 輸出出錯語句涉及到的相關變量的值和類型 ,能夠幫助分析出錯緣由。
c. 找出出錯位置。 每每錯誤的緣由並不在報錯的位置,因此多輸出一些標記,多 print 不一樣位置的變量值, 查看變量在運行過程當中值的變化狀況 ,能夠觀察是在哪裏發生了問題。
幾個經過 log 調試的經驗技巧:
a. 多輸出一些輔助信息 ,方便本身查看,否則一堆數據看花眼。好比我通常輸出時會標註上 變量名,再輸出變量類型,以及變量的值 。好比:
b. 在出錯行以前輸出 。報錯行涉及的一些變量,他們的數值和類型,全都輸出出來,看看和預期是否一致。
c. 一行作一件事 。若是你出錯的一行裏連續調用了多個函數或運算,請分開寫,分開輸出。
d. 對於字符串 ,直接 print 會被轉義和解碼,影響對變量實際值的觀察。能夠用 print(repr(text)) 或 print([text]) 的方式查看。
e. 對於編碼問題,用好 type 方法和 chardet 庫輔助判斷 。這點以前編碼相關的文章裏有說明, 公衆號裏回覆 pycharm 可查看 。
f. 爲了方便記錄和回溯問題日誌,一般也會 將 log 輸出到文件 。也有專門的 logging 模塊作這事。
記住: print 不要錢,能用多少是多少! 確保你清楚程序運行的狀態細節。
斷點調試看參考以前文章 如何在 Python 中使用斷點調試,這裏再也不復述。
前面這些基本是操做層面的具體 debug 方法,下面我再來談點 debug 的思想和原則 :
軟件開發中有一個「單元測試」的概念:若是你寫了一個函數,應該先運行下這個函數是否是正常,各類參數下會不會出現錯誤。這樣能夠 把問題控制在較小的範圍內 解決。
好比作爬蟲沒有抓到正確數據,那麼究竟是 (1)請求來的數值不對,仍是 (2)文本處理方法不對?若是你認爲是文本處理方法沒有問題,就手動給定一個正確格式的字符串文本,應該能夠獲得正確的結果。這就至關於 控制了因素(2),只改變因素(1),根據執行結果就能夠確認或排除問題的所在 。
二分查找法是一個定位問題的技巧。若是你的代碼裏有問題,那麼問題要麼在前半段,要麼在後半段。你先把後半段代碼去掉執行,看看程序是否還報錯,就知道錯誤在哪部分。依次類推, 不斷折半,直到找到引起報錯的代碼 。
有的錯誤不是每次出現。這時候最好別急着去改代碼,而是 想辦法能夠穩定重現問題 。當你能順利重現問題的時候,一般離分析解決它也不遠了。解決了以後, 再按照以前重現的方式驗證修改 是否確實有效。
不管是開發代碼,仍是調試 debug,在作一個動做前要清楚本身的目的是什麼,而不是盲目地進行改動。 不要猜! 我常常會看見一些新手遇到問題以後,反覆執行代碼,或者不斷調整參數,妄想某次執行程序就能神奇地經過了。這是一個很很差的態度,請避免。 要恪守邏輯 ,知道如今要解決的問題是什麼,須要獲得那些信息,可能的假設是什麼,如何經過修改代碼去驗證你的判斷,這樣纔是合理的 debug 方式。
以上就是一些 debug 的基本思想和技巧。這裏僅僅是概要精華,操做起來遠不止這麼多,同時還須要實際的練習才能掌握。我能作的就是給你的編程技能樹下埋一顆種子,能不能生根發芽,就看各位本身的澆灌了。(我相信,即便我這裏都說過了,仍是會有不少人依舊犯上述說起的錯誤 ╮(╯_╰)╭ 隨緣吧,師傅領進門,修行在我的……)
想要深刻了解更多編程的思想和技巧,歡迎來咱們的 碼上行動 或 知識星球 。
下課!
════
其餘文章及回答:
如何自學Python | 新手引導 | 精選Python問答 | Python單詞表 | 知乎下載器 | 人工智能 | 嘻哈 | 爬蟲 | 我用Python | 高考 | requests | AI平臺
歡迎搜索及關注: Crossin的編程教室