- Linux集群之美
- 余洪春
- 1783字
- 2021-01-08 10:57:48
2.5.5 Python異常處理與程序調(diào)試異常
Exception是任何語言必定存在的一部分。Python提供了強(qiáng)大的異常處理機(jī)制,可通過捕獲異常來提高程序的健壯性。異常處理還具有釋放對象、中止循環(huán)的運行等作用。在程序運行的過程中,如果發(fā)生了錯誤,可以事先約定返回一個錯誤代碼,這樣就可以知道是否有錯,以及出錯的原因。在操作系統(tǒng)提供的調(diào)用中,返回錯誤碼非常常見。比如打開文件的函數(shù)open(),成功時返回文件描述符(就是一個整數(shù)),出錯時返回-1值。用錯誤碼來表示是否出錯十分不便,因為應(yīng)該返回的正常結(jié)果會和錯誤碼混在一起,造成調(diào)用者必須用大量的代碼來判斷是否出錯。一旦出錯,還要一級一級上報,直到某個函數(shù)可以處理該錯誤(比如,給用戶輸出一個錯誤信息)。所以高級語言通常都內(nèi)置了一套try...except...finally...的錯誤處理機(jī)制,Python也不例外。
1.try...except語句
try...except語句用于處理問題語句,捕獲可能存在的異常。try子句中的代碼塊用于放置可能出現(xiàn)異常的語句,except子句中的代碼塊用于處理異常。當(dāng)異常出現(xiàn)時,Python會自動生成一個異常對象。該對象包括異常的具體信息,以及異常的種類和錯誤位置。我們舉個簡單的例子:
#!/usr/bin/env python #-*- coding:utf-8 -*- try: open('test.txt','r') #嘗試獲取一個不存在的文件 print "該文件是正常的" except IOError: #捕獲I/O異常,如果是Python 3.7版本,這里是FileNotFoundError異常 print "該文件不存在" except: print "程序異常!" #其他異常情況
try...except語句后面還可以添加一個finally語句,這種方式主要用于無論異常是否發(fā)生,finally子句都會被執(zhí)行的情況。所有的finally子句都用于關(guān)閉因異常而不能釋放的系統(tǒng)資源。還是以上面的例子為例,在后面加上finally子句:
#!/usr/bin/env python #-*- coding:utf-8 -*- try: f = open('test1.py','r') try: print f.read() except: print "該文件是正常的" finally: print "釋放資源" f.close() except IOError: print "文件不存在!"
我們用finally語句的本意是想關(guān)閉因異常而不能釋放的系統(tǒng)資源,比如關(guān)閉文件。但隨著語句的增多,try...finally顯然不夠簡潔,用with...as(上下文管理器)語句可以很簡潔地實現(xiàn)以上功能:
with open('test1.py','w') as f: f.write('Hello ') f.write('World')
這樣不僅能處理出現(xiàn)異常的情況,而且還可以避免出現(xiàn)在open()一個文件后忘記寫close()方法的情況。
此外,當(dāng)程序中出現(xiàn)錯誤時,Python會自動引發(fā)異常,也可以通過raise語句顯式地引發(fā)異常。一旦執(zhí)行了raise語句,raise語句后的代碼將不能被執(zhí)行。示例如下:
#!/usr/bin/env python #-*- encoding:utf-8 -*- try: s = None if s is None: print "s是對空對象" print len(s) except TypeError: print "空對象是沒有長度的"
第三行程序判斷變量s的值是否為空,如果為空,則拋出異常NameError;由于執(zhí)行了NameError異常,所以該代碼后的代碼將不會被執(zhí)行。
2.調(diào)試
當(dāng)程序中出現(xiàn)異常或錯誤時,最后的解決方法就是調(diào)試程序,那么一般包含哪些方法呢?通常有如下5種方法:
·編輯器自帶的調(diào)試功能
·print方法
·斷言(assert)方法
·logging模塊
·pdb方法
Python的專業(yè)編程器,例如PyCharm IDE本身就帶了Python程序的Debug調(diào)試功能,這里就不進(jìn)行詳細(xì)說明了,下面只針對其余幾種情況來說明。
(1)print方法
print方法很好理解,這也是我們寫程序經(jīng)常用到的一種方法,即我們認(rèn)為某變量有問題或需要知道某變量時,將它打印出來即可,雖然簡單粗暴,但確實有效。但這樣也會帶來一個問題,復(fù)雜的業(yè)務(wù)邏輯中會有大量變量,這樣程序中會充斥著大量的print語句,如果調(diào)試完成以后不注意清理,也會帶來很多問題。
(2)斷言方法
assert語句用于檢測某個條件表達(dá)式是否為真。
用assert代替print是種很好的選擇?想想我們的程序里到處都是print,運行結(jié)果也會包含很多垃圾信息。理論上,程序中有print出現(xiàn)的地方,都可以用assert來代替。如果assert語句斷言失敗,則會引發(fā)AssertionError異常。
舉個簡單的例子:
a = 'hello' assert len(a) == 1
執(zhí)行下面這段代碼,會報錯:
AssertionError Traceback (most recent call last) <ipython-input-4-ce3ea8375b99> in <module>() ----> 1 assert len(t) <= 1 AssertionError:
(3)logging模塊
當(dāng)Python程序的代碼量達(dá)到一定數(shù)量時,使用logging就是一種好的選擇。logging不僅能輸出到控制臺,還能寫入文件,且能使用TCP協(xié)議將日志信息發(fā)送到網(wǎng)絡(luò),功能十分強(qiáng)大。示例如下:
#!/usr/bin/env python import logging logging.debug('debug message') logging.info('info message') logging.warn('warn message') logging.error('error message') logging.critical('critical message')
執(zhí)行下面這段代碼,結(jié)果如下:
WARNING:root:warn message ERROR:root:error message CRITICAL:root:critical message
默認(rèn)情況下,logging模塊會將日志打印到屏幕上,日志級別為WARNING(即只有日志級別高于WARNING的信息才會輸出),我們可以在合理的程序中使用logging模塊代替print命令,這樣寫出來的程序在排錯時會非常高效。
(4)pdb方法
使用Python的調(diào)試器pdb可讓程序以單步的方法運行,以便隨時查看程序的執(zhí)行狀態(tài)。
我們先故意寫一個有問題的Python程序,名字叫err.py,內(nèi)容如下:
#!/usr/bin/env python s = '0' n = int(s) print 10/n
然后在Linux環(huán)境下以pdb模式執(zhí)行程序,如下:
python -m pdb test0.py
l表示可以查看代碼全部完整內(nèi)容,n是一步一步執(zhí)行代碼,p +變量名表示可以隨時打印程序中的變量名,這里大家自行演示。
雖然這些方法都有各自的好處,但隨著我們開發(fā)的項目越來越多,代碼量越來越大時,大家會發(fā)現(xiàn),logging模塊才是最有效率的辦法。
- 每天5分鐘玩轉(zhuǎn)Kubernetes
- Linux操作系統(tǒng)基礎(chǔ)
- Mobile-first Bootstrap
- Persistence in PHP with the Doctrine ORM
- Haskell Financial Data Modeling and Predictive Analytics
- Windows Phone 7.5 Data Cookbook
- Ubuntu Linux操作系統(tǒng)
- Kubernetes從入門到實踐
- Mobile First Design with HTML5 and CSS3
- Linux設(shè)備驅(qū)動開發(fā)
- Django Project Blueprints
- Java EE 7 Developer Handbook
- Learn Quantum Computing with Python and IBM Quantum Experience
- Windows Azure實戰(zhàn)
- Azure Serverless Computing Cookbook