1.錯(cuò)誤處理
try
try內(nèi)的代碼一旦出錯(cuò)就會(huì)跳轉(zhuǎn)到except語(yǔ)句塊并且在出錯(cuò)代碼處停止繼續(xù)執(zhí)行,然后在執(zhí)行完except后蹂析,如果有finally語(yǔ)句塊舔示,則執(zhí)行finally語(yǔ)句塊。
那么如果try不出錯(cuò)那电抚?
執(zhí)行完try語(yǔ)句塊后惕稻,不在執(zhí)行except語(yǔ)句塊的內(nèi)容,但是還會(huì)執(zhí)行finally語(yǔ)句塊蝙叛。
又因?yàn)殄e(cuò)誤有很多種俺祠,所以就會(huì)有多個(gè)except來(lái)捕獲不同類(lèi)型的錯(cuò)誤苦蒿。
注意:因?yàn)殄e(cuò)誤類(lèi)型也是類(lèi)有繼承關(guān)系茵烈,所以就有以下例子發(fā)生某残。
第二個(gè)except永遠(yuǎn)也捕獲不到UnicodeError鸡挠,因?yàn)閁nicodeError是ValueError的子類(lèi)十拣,如果有舌厨,也被第一個(gè)except給捕獲了刨疼。
常見(jiàn)的錯(cuò)誤類(lèi)型和繼承關(guān)系查看地址如下:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy
跨越多層調(diào)用
比如函數(shù)main()調(diào)用foo()专缠,foo()調(diào)用bar()狰挡,結(jié)果bar()出錯(cuò)了捂龄,這時(shí)释涛,只要main()捕獲到了。
調(diào)用棧
如果錯(cuò)誤沒(méi)有被捕獲倦沧,就會(huì)入棧被捕獲并且被打印出來(lái)唇撬。
我們由上往下看打印的錯(cuò)誤信息。從20行的main()方法的執(zhí)行開(kāi)始追本溯源展融,按照邏輯最終找到了15行出的錯(cuò)誤窖认。
注意:因此出錯(cuò)的時(shí)候一定要仔細(xì)推敲打印的錯(cuò)誤信息
記錄錯(cuò)誤
利用Python內(nèi)置的logging模塊可以非常容易地記錄錯(cuò)誤信息并且打印完錯(cuò)誤信息后會(huì)繼續(xù)執(zhí)行,最后正常退出告希。
通過(guò)配置扑浸,logging還可以把錯(cuò)誤記錄到日志文件里,方便事后排查燕偶。
自定義一個(gè)類(lèi)接收拋出錯(cuò)誤
根據(jù)需要喝噪,可以定義一個(gè)錯(cuò)誤的class,選擇好繼承關(guān)系指么,然后酝惧,用raise語(yǔ)句拋出一個(gè)錯(cuò)誤。
注意:盡量使用Python內(nèi)置的錯(cuò)誤類(lèi)型伯诬。
raise語(yǔ)句
raise語(yǔ)句如果不帶參數(shù)晚唇,就會(huì)把當(dāng)前錯(cuò)誤原樣拋出。
在打印一個(gè)ValueError!后盗似,又把錯(cuò)誤通過(guò)raise語(yǔ)句拋出去了的目的是:
捕獲錯(cuò)誤目的只是記錄一下哩陕,便于后續(xù)追蹤。
2.調(diào)試
第一種方法把可能有問(wèn)題的變量打印出來(lái)桥言,但是壞處是將來(lái)還得刪掉它并且運(yùn)行結(jié)果也會(huì)包含很多垃圾信息萌踱。
第二種方法凡是用print()來(lái)輔助查看的地方,都可以用斷言(assert)來(lái)替代:
(這里代碼出了問(wèn)題号阿,例子之后補(bǔ)上并鸵。)
第三種方式是把print()替換為logging,和assert比扔涧,logging不會(huì)拋出錯(cuò)誤园担,而且可以輸出到文件。
它允許你指定記錄信息的級(jí)別枯夜,有debug弯汰,info,warning湖雹,error等幾個(gè)級(jí)別咏闪,當(dāng)我們指定level=INFO時(shí),logging.debug就不起作用了摔吏。同理鸽嫂,指定level=WARNING后纵装,debug和info就不起作用了。這樣一來(lái)据某,你可以放心地輸出不同級(jí)別的信息橡娄,也不用刪除,最后統(tǒng)一控制輸出哪個(gè)級(jí)別的信息癣籽。
第四種方式是啟動(dòng)Python的調(diào)試器pdb挽唉,讓程序以單步方式運(yùn)行,可以隨時(shí)查看運(yùn)行狀態(tài)筷狼。
啟動(dòng)后瓶籽,pdb定位到下一步要執(zhí)行的代碼并且在此行代碼處會(huì)出現(xiàn)->符號(hào)。
l:查看代碼
n:只執(zhí)行一行的代碼
p 變量名:查看變量
q:結(jié)束調(diào)試
第五種方式桑逝,這個(gè)方法也是用pdb棘劣,但是不需要單步執(zhí)行俏让,我們只需要import pdb楞遏,然后,在可能出錯(cuò)的地方放一個(gè)pdb.set_trace()首昔,就可以設(shè)置一個(gè)斷點(diǎn)寡喝。
程序會(huì)自動(dòng)在pdb.set_trace()暫停并進(jìn)入pdb調(diào)試環(huán)境,命令c會(huì)繼續(xù)運(yùn)行勒奇。
第六種方式是一個(gè)支持調(diào)試功能的IDE预鬓。
注意:logging才是最好用的調(diào)試工具
3.單元測(cè)試
單元測(cè)試是用來(lái)對(duì)一個(gè)模塊、一個(gè)函數(shù)或者一個(gè)類(lèi)來(lái)進(jìn)行正確性檢驗(yàn)的測(cè)試工作赊颠。
4.文檔測(cè)試
代碼與其他說(shuō)明可以寫(xiě)在注釋中格二,然后,由一些工具來(lái)自動(dòng)生成文檔竣蹦。
只要這些代碼本身就可以直接運(yùn)行顶猜,那么就可以自動(dòng)執(zhí)行寫(xiě)在注釋中的這些代碼。
這就是Python內(nèi)置的“文檔測(cè)試”(doctest)模塊痘括,他可以直接提取注釋中的代碼并執(zhí)行測(cè)試长窄。
通過(guò)'''來(lái)把“文檔測(cè)試”(doctest)模塊的內(nèi)容包圍起來(lái)即可。
doctest嚴(yán)格按照Python交互式命令行的輸入和輸出來(lái)判斷測(cè)試結(jié)果是否正確纲菌。只有測(cè)試異常的時(shí)候挠日,可以用...表示中間一大段煩人的輸出。
什么輸出也沒(méi)有翰舌。這說(shuō)明我們編寫(xiě)的doctest運(yùn)行都是正確的嚣潜。
如果程序有問(wèn)題的話(huà),再運(yùn)行就會(huì)報(bào)錯(cuò)椅贱!
當(dāng)模塊正常導(dǎo)入時(shí)懂算,doctest不會(huì)被執(zhí)行唉韭。只有在命令行直接運(yùn)行時(shí),才執(zhí)行doctest犯犁。