錯誤:有的錯誤是程式編寫有問題造成的,比如本來應該輸出整數結果輸出了字元串,這種錯誤我們通常稱之為bug,bug是必須修複的;有的錯誤是使用者輸入造成的,比如讓使用者輸入email位址,結果得到一個空字元串,這種錯誤可以通過檢查使用者輸入來做相應的處理。還有一類錯誤是完全無法在程式運作過程中預測的,比如寫入檔案的時候,磁盤滿了,寫不進去了,或者從網絡抓取資料,網絡突然斷掉了。這類錯誤也稱為異常,在程式中通常是必須處理的,否則,程式會因為各種問題終止并退出。
調試:跟蹤程式的執行,檢視變量的值是否正确,這個過程稱為調試。Python的pdb可以讓我們以單步方式執行代碼
測試:編寫測試也很重要。有了良好的測試,就可以在程式修改後反複運作,確定程式輸出符合我們編寫的測試。
錯誤處理:在程式運作的過程中,如果發生了錯誤,可以事先約定傳回一個錯誤代碼,這樣,就可以知道是否有錯,以及出錯的原因。在作業系統提供的調用中,傳回錯誤碼非常常見。比如打開檔案的函數open(),成功時傳回檔案描述符(就是一個整數),出錯時傳回-1。用錯誤碼來表示是否出錯十分不便,因為函數本身應該傳回的正常結果和錯誤碼混在一起,造成調用者必須用大量的代碼來判斷是否出錯。
進階語言通常都内置了一套
try...except...finally...
的錯誤處理機制,Python也不例外。
try:
print('try:')
r=10/0
print(r)
except(ZeroDivisionError,IndexError,ValueError):
print('excep:',TypeError,IndexError,ValueError)
finally:
print('finally..')
print('end')
#tracking error
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('2')
main()
Python的錯誤其實也是class,所有的錯誤類型都繼承自
BaseException
,是以在使用
except
時需要注意的是,它不但捕獲該類型的錯誤,還把其子類也“一網打盡”。如果錯誤沒有被捕獲,它就會一直往上抛,最後被Python解釋器捕獲,列印一個錯誤資訊,然後程式退出。Python内置的
logging
子產品可以非常容易地記錄錯誤資訊。
因為錯誤是class,捕獲一個錯誤就是捕獲到該class的一個執行個體。是以,錯誤并不是憑空産生的,而是有意建立并抛出的。Python的内置函數會抛出很多類型的錯誤,我們自己編寫的函數也可以抛出錯誤。
如果要抛出錯誤,首先根據需要,可以定義一個錯誤的class,選擇好繼承關系,然後,用
raise
語句抛出一個錯誤的執行個體:
# err.py
class FooError(StandardError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
隻有在必要的時候才定義我們自己的錯誤類型。如果可以選擇Python已有的内置的錯誤類型(比如ValueError,TypeError),盡量使用Python内置的錯誤類型。
下面為錯誤類型和繼承關系:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning