如何調(diào)試您的Python代碼?
譯文【51CTO.com快譯】對(duì)于碼農(nóng)而言,如果說能夠編寫出有效的代碼,會(huì)給他們帶來滿滿的成就感的話;那么當(dāng)其代碼中出現(xiàn)缺陷、甚至是錯(cuò)誤時(shí),他們則會(huì)產(chǎn)生深深的挫敗感。因此,為了避免在軟件運(yùn)行的過程中,出現(xiàn)各種意想不到的錯(cuò)誤,我們需要通過針對(duì)程序的調(diào)試,來消除各種代碼級(jí)別的錯(cuò)誤。本文將以Python為例,和您討論八種有關(guān)代碼調(diào)試的優(yōu)秀實(shí)踐。
何為Python異常?
每當(dāng)Python無法解釋某段目標(biāo)代碼或命令時(shí),程序往往會(huì)拋出異常。Python的各種異常,實(shí)際上是Python在執(zhí)行代碼時(shí),出現(xiàn)的一組錯(cuò)誤集合。
通常,Python會(huì)使用try和except塊,來觸發(fā)各種錯(cuò)誤異常。由于可執(zhí)行的命令往往位于try塊之內(nèi),因此當(dāng)try中的代碼出現(xiàn)失敗時(shí),Python就會(huì)去執(zhí)行except塊中的代碼。也就是說,except關(guān)鍵字中的語句本質(zhì)上就是try塊中的那些異常,Python只是將它們作為錯(cuò)誤而觸發(fā)罷了。當(dāng)然,一個(gè)try...except塊有時(shí)候也可能會(huì)包含多個(gè)帶有except關(guān)鍵字的異常。其中包含了許多我們在Python中常見的典型錯(cuò)誤與詳細(xì)信息。
由于我們在使用各種內(nèi)置函數(shù)、軟件庫或Python框架時(shí),都可能會(huì)碰到異常,因此,即便您認(rèn)真編寫和遵守了正確的語法,也無法保證相關(guān)方法在調(diào)用和執(zhí)行時(shí)不會(huì)出錯(cuò)。例如,您可能只編寫了大約5行代碼,但是Python程序會(huì)發(fā)現(xiàn)到您正在使用的某個(gè)庫、框架或內(nèi)置方法的源代碼中,存在著預(yù)定義的相關(guān)異常,因此會(huì)在第200行處觸發(fā)異常錯(cuò)誤。
語法錯(cuò)誤
當(dāng)程序代碼無法在語法層面上被識(shí)別時(shí),Python通常會(huì)拋出語法級(jí)別的錯(cuò)誤。如果您是Python的初學(xué)者,那么就可能會(huì)頻繁地遇到此類語法錯(cuò)誤。不過,由于這些錯(cuò)誤比那些深層次的異常(in-depth exceptions)更易于被追溯,因此您一旦掌握了基本原理,就很容易對(duì)它們進(jìn)行合理的處理。
如何調(diào)試你的Python代碼
Python的典型異常包括:縮進(jìn)、類型、以及名稱錯(cuò)誤等方面。它們既可能來自單行代碼,也可能源于某個(gè)代碼塊。我們雖然沒有統(tǒng)一的方法對(duì)其進(jìn)行處置,但是可以根據(jù)各種實(shí)例和項(xiàng)目類型,去予以應(yīng)對(duì)。下面,讓我們來具體討論可用于調(diào)試Python的八種方法。它們既可以被單獨(dú)使用,也能夠通過組合來增強(qiáng)效果。
1.檢查錯(cuò)誤描述
處理Python錯(cuò)誤的可用方法之一是查看錯(cuò)誤的描述。Python通常會(huì)在其錯(cuò)誤輸出的最后一行給予詳細(xì)的說明。例如:在解析意外的EOF(End Of File)時(shí),我們會(huì)發(fā)現(xiàn)它們通常與缺少括號(hào)有關(guān)。也就是說,當(dāng)您嘗試著從類或?qū)ο筇幷{(diào)用某個(gè)錯(cuò)誤的函數(shù)時(shí),就會(huì)出現(xiàn)AttributeError之類無效的語法(invalid syntax)錯(cuò)誤。因此,通過最終一行的“蛛絲馬跡”,您往往能夠成功地追蹤錯(cuò)誤的來源,并著手重寫其相關(guān)的代碼。
2.追蹤錯(cuò)誤的來源
Python的錯(cuò)誤具有較強(qiáng)的代碼行限定性(line-bound),在遇到錯(cuò)誤時(shí),您需要注意Python所指向的具體行號(hào)。例如,由于下面的代碼會(huì)嘗試著連接不同的數(shù)據(jù)類型(字符串和整數(shù)),因此會(huì)產(chǎn)生類型方面的錯(cuò)誤(type error)。其錯(cuò)誤信息指向了示例代碼中的第2行:
示例代碼:
- db = open("output.txt", "a")
- a = "Hello"+1
- b = "How do you do?"
- db.write(a+", "+b+"
- ")
錯(cuò)誤信息:
- raceback (most recent call last):
- File "C:\Users\Omisola Idowu\Desktop\Lato
- oup
- ew.py", line 2, in
- a = "Hello"+1
- TypeError: can only concatenate str (not "int") to str
下面讓我們再來看另一個(gè)錯(cuò)誤示例:
代碼:
- def findTotal(a):
- for i in a
- print(sum(i)*2)
錯(cuò)誤信息:
- File "C:\Users\Omisola Idowu\Desktop\Lato
- oup
- ew.py", line 2
- for i in a
- ^
- SyntaxError: invalid syntax
顯然,Python指出了第2行的語法錯(cuò)誤。如果您熟悉Python的話,就能夠一眼看出:實(shí)際上,這是因?yàn)樵趂or循環(huán)后面缺少的一個(gè)冒號(hào)。
3.在命令行上利用Trace方法
雖然您可以使用內(nèi)置的集成開發(fā)和學(xué)習(xí)環(huán)境(Integrated Development and Learning Environment,IDLE)去調(diào)試Python,但是它不一定適合大型的軟件項(xiàng)目。因此,調(diào)試Python的可用方法之一實(shí)際上是采用命令行界面(command-line interface,CLI)。它與在JavaScript中運(yùn)行console.log()有著相似的效果。
如果您在代碼執(zhí)行過程中遇到了錯(cuò)誤,則可以啟動(dòng)CLI,并使用trace命令去試著運(yùn)行有問題的腳本。其基本工作原理是對(duì)代碼進(jìn)行逐行檢查,并對(duì)發(fā)現(xiàn)問題的地方予以解析。
若要調(diào)用該方法,請(qǐng)?jiān)诿钚兄?,以如下方式運(yùn)行代碼文件:
- python -m trace --trace file_name.py
在大型項(xiàng)目中,雖然以上述方式運(yùn)行整個(gè)腳本并不切實(shí)際,但是您可以創(chuàng)建一個(gè)單獨(dú)的Python文件,將每個(gè)代碼塊(一次僅一段)逐個(gè)粘貼到該文件中,然后分別運(yùn)行上述命令。在此,您可以將其視為單元性調(diào)試的一種特有形式。
4.測試您的代碼
除了上述提到的異常原因之外,錯(cuò)誤的布爾值(boolean)有時(shí)也會(huì)導(dǎo)致您的程序在部署中表現(xiàn)異常或出現(xiàn)錯(cuò)誤。單元測試往往涉及到需要隔離代碼中的某些單元(塊或行),以測試具體的性能、效率、以及正確性等指標(biāo)。它們對(duì)于程序代碼而言都是極其重要的。在單元測試中,我們可以使用多種調(diào)試技術(shù),來通過assert函數(shù)對(duì)代碼的正確性進(jìn)行分析,以及檢查代碼在運(yùn)行過程中所需的時(shí)間等維度指標(biāo)。
在實(shí)際生產(chǎn)環(huán)境中,我們可以創(chuàng)建一個(gè)名為test.py的單獨(dú)Python文件,并在該文件中測試每個(gè)代碼單元。如下代碼段展示了單元測試的一個(gè)示例:
- data = {
- "guitars":[
- {"Seagull":"$260"},
- {"Fender":"$700"},
- {"Electric-acoustic":"$600"}
- ]
- }
- if len(data["guitars"])==2:
- for i in data["guitars"]:
- print(i)
- assert len(data["guitars"])==2, "Length less than what's required, should be 3"
可見,由于數(shù)組的長度小于3,因此Python會(huì)觸發(fā)如下斷言錯(cuò)誤:
- AssertionError: Length less than what's required, should be 3
5.使用日志
作為調(diào)試代碼的另一種方法,Python內(nèi)置了一套日志庫,可供日志的檢查與勘誤。您可以通過鏈接--https://docs.python.org/3/howto/logging.html,來進(jìn)一步了解其工作原理,以及如何在控制臺(tái)中的運(yùn)行和捕獲它們。如果您覺得在部署應(yīng)用的過程中,無法通過控制臺(tái)來查看到日志,則可以通過設(shè)置簡單郵件傳輸協(xié)議(SMTP),以便于將代碼日志以電子郵件的方式及時(shí)捕獲與分析。
6.使用標(biāo)準(zhǔn)的Python調(diào)試器
Python有一個(gè)被稱為pdb的、非常流行的板載調(diào)試器。由于它是內(nèi)置的,因此您只需要將pdb導(dǎo)入待測試文件中即可。pdb模塊可以通過對(duì)代碼采取事后執(zhí)行(post-mortem)的方式,來調(diào)試程序在運(yùn)行過程中出現(xiàn)的突然崩潰現(xiàn)象。
您既可以將pdb用于運(yùn)行整個(gè)Python文件,也可以僅執(zhí)行某個(gè)單元,以深入到程序的每一行去發(fā)現(xiàn)潛在的錯(cuò)誤。在實(shí)際使用中,您需要首先打開Python文件,然后通過importpdb;pdb.set_trace(),來啟動(dòng)pdb調(diào)試器。接著,您可以通過CLI運(yùn)行待測試的Python文件(請(qǐng)參見--https://www.makeuseof.com/run-python-script/):
- Python Your_Python_file.py
通過如下帶有h的命令,您可以查看到pdb的所有可用命令列表:
- (pdb) h
列表的輸出如下圖所示:
例如,您可以通過如下命令,來逐行羅列出代碼:
- (pdb) l
7.使用IDE進(jìn)行調(diào)試
IDE也是用于調(diào)試Python腳本的寶貴工具。其中:
- Visual Studio Code(https://code.visualstudio.com/download)能夠協(xié)助您運(yùn)行與調(diào)試Python程序中的各項(xiàng)功能。
- 作為一種語言類支持插件,Pylance可允許您在調(diào)試的模式下運(yùn)行自己的代碼。
- 作為另一個(gè)出色的IDE,Pycharm(https://www.jetbrains.com/pycharm/download/)可以幫助您更加深入地查找代碼中的錯(cuò)誤。
- Eclipse(http://www.eclipse.org/downloads/packages/)也提供了一個(gè)名為Pydev的第三方插件,以實(shí)現(xiàn)針對(duì)Python腳本的輕松調(diào)試。
8.在網(wǎng)上搜索解決方案
鑒于Python具有龐大的開發(fā)者社區(qū),您不妨將互聯(lián)網(wǎng)作為尋找解決Python代碼問題的可靠資源。例如,Stackoverflow(https://stackoverflow.com/)便是一個(gè)流行的代碼社區(qū),您可以在其中進(jìn)行各種互動(dòng)式的問答。當(dāng)然,YouTube上也包含了大量的有關(guān)Python編程的實(shí)用視頻。
原文標(biāo)題:How to Debug Your Python Code,作者:IDOWU OMISOLA
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】