目錄
-
- 1 錯誤
- 2 異常
-
- 2.1 內置異常
- 2.2 異常處理
- 2.3 拋出異常
- 2.4 自定義異常
程序中的錯誤我們通常稱為 bug ,工作中我們不僅需要改自己程序中的 bug ,還需要改別人程序中的 bug ,新項目有 bug 要改,老項目也有 bug 要改,可以說 bug 幾乎貫穿一個程序員的職業生涯…
我們通常將 bug 分為 Error(錯誤) 和 Exception(異常),我們下面來具體學習下 Python 中的 錯誤 和 異常。
1 錯誤
錯誤 通常是指程序中的 語法錯誤 或 邏輯錯誤,來通過兩個 Python 例子看一下:
語法錯誤示例
# print前面少了 :
if Trueprint("hello python")
我們編寫程序通常使用開發工具編寫,比如:我使用 Pycharm 工具編寫 Python 程序,像這種語法錯誤,在編寫程序時,編譯器就會檢測出來并提示我們,因此,我們編寫好的程序幾乎不會出現這種問題。
邏輯錯誤示例
# 0 是不能作為被除數的
a = 5
b = 0
print(a/b)#執行結果:ZeroDivisionError: division by zero
邏輯錯誤編譯器是不會提示我們的,因此,我們編寫程序時,對一些基本常識要有一定了解,從而,避免出現邏輯錯誤。
2 異常
即便 Python 程序的語法是正確的,在運行它的時候,也有可能發生錯誤,運行期檢測到的錯誤被稱為異常;大多數的異常都不會被程序處理,都以錯誤信息的形式展現。
2.1 內置異常
我們先來看一下異常層次結構:
BaseException+-- SystemExit+-- KeyboardInterrupt+-- GeneratorExit+-- Exception+-- StopIteration+-- StopAsyncIteration+-- ArithmeticError| +-- FloatingPointError| +-- OverflowError| +-- ZeroDivisionError+-- AssertionError+-- AttributeError+-- BufferError+-- EOFError+-- ImportError| +-- ModuleNotFoundError+-- LookupError| +-- IndexError| +-- KeyError+-- MemoryError+-- NameError| +-- UnboundLocalError+-- OSError| +-- BlockingIOError| +-- ChildProcessError| +-- ConnectionError| | +-- BrokenPipeError| | +-- ConnectionAbortedError| | +-- ConnectionRefusedError| | +-- ConnectionResetError| +-- FileExistsError| +-- FileNotFoundError| +-- InterruptedError| +-- IsADirectoryError| +-- NotADirectoryError| +-- PermissionError| +-- ProcessLookupError| +-- TimeoutError+-- ReferenceError+-- RuntimeError| +-- NotImplementedError| +-- RecursionError+-- SyntaxError| +-- IndentationError| +-- TabError+-- SystemError+-- TypeError+-- ValueError| +-- UnicodeError| +-- UnicodeDecodeError| +-- UnicodeEncodeError| +-- UnicodeTranslateError+-- Warning+-- DeprecationWarning+-- PendingDeprecationWarning+-- RuntimeWarning+-- SyntaxWarning+-- UserWarning+-- FutureWarning+-- ImportWarning+-- UnicodeWarning+-- BytesWarning+-- ResourceWarning
通過上面的異常層次結構,我們可以清晰的看出,BaseException為所有異常的基類,其下面分為:SystemExit、KeyboardInterrupt、GeneratorExit、Exception 四類異常,Exception 為所有非系統退出類異常的基類,Python 提倡繼承 Exception 或其子類派生新的異常;Exception 下包含我們常見的多種異常如:MemoryError(內存溢出)、BlockingIOError(IO異常)、SyntaxError(語法錯誤異常)… 詳細說明可以查看下面列表:
異常名稱 | 描述 |
---|---|
BaseException | 所有異常的基類 |
SystemExit | 解釋器請求退出 |
KeyboardInterrupt | 用戶中斷執行(通常是輸入^C) |
Exception | 常規錯誤的基類 |
StopIteration | 迭代器沒有更多的值 |
GeneratorExit | 生成器(generator)發生異常來通知退出 |
StandardError | 所有的內建標準異常的基類 |
ArithmeticError | 所有數值計算錯誤的基類 |
FloatingPointError | 浮點計算錯誤 |
OverflowError | 數值運算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有數據類型) |
AssertionError | 斷言語句失敗 |
AttributeError | 對象沒有這個屬性 |
EOFError | 沒有內建輸入,到達EOF 標記 |
EnvironmentError | 操作系統錯誤的基類 |
IOError | 輸入/輸出操作失敗 |
OSError | 操作系統錯誤 |
WindowsError | 系統調用失敗 |
ImportError | 導入模塊/對象失敗 |
LookupError | 無效數據查詢的基類 |
IndexError | 序列中沒有此索引(index) |
KeyError | 映射中沒有這個鍵 |
MemoryError | 內存溢出錯誤(對于Python 解釋器不是致命的) |
NameError | 未聲明/初始化對象 (沒有屬性) |
UnboundLocalError | 訪問未初始化的本地變量 |
ReferenceError | 弱引用(Weak reference)試圖訪問已經垃圾回收了的對象 |
RuntimeError | 一般的運行時錯誤 |
NotImplementedError | 尚未實現的方法 |
SyntaxError | Python 語法錯誤 |
IndentationError | 縮進錯誤 |
TabError | Tab 和空格混用 |
SystemError | 一般的解釋器系統錯誤 |
TypeError | 對類型無效的操作 |
ValueError | 傳入無效的參數 |
UnicodeError | Unicode 相關的錯誤 |
UnicodeDecodeError | Unicode 解碼時的錯誤 |
UnicodeEncodeError | Unicode 編碼時錯誤 |
UnicodeTranslateError | Unicode 轉換時錯誤 |
Warning | 警告的基類 |
DeprecationWarning | 關于被棄用的特征的警告 |
FutureWarning | 關于構造將來語義會有改變的警告 |
OverflowWarning | 舊的關于自動提升為長整型(long)的警告 |
PendingDeprecationWarning | 關于特性將會被廢棄的警告 |
RuntimeWarning | 可疑的運行時行為(runtime behavior)的警告 |
SyntaxWarning | 可疑的語法的警告 |
UserWarning | 用戶代碼生成的警告 |
2.2 異常處理
Python 程序捕捉異常使用 try/except 語句,先看個例子:
# 1.被除數為 0,未捕獲異常
def getNum(n):return 10 / n
print(getNum(0))
#輸出結果: ZeroDivisionError: division by zero# 2.捕獲異常
def getNum(n):try:return 10 / nexcept IOError:print('Error: IOError argument.')except ZeroDivisionError:print('Error: ZeroDivisionError argument.')
print(getNum(0))
'''
輸出結果:
Error: ZeroDivisionError argument.
None
'''
try 語句的工作方式為:
-
首先,執行 try 子句 (在 try 和 except 關鍵字之間的部分);
-
如果沒有異常發生, except 子句 在 try 語句執行完畢后就被忽略了;
-
如果在 try 子句執行過程中發生了異常,那么該子句其余的部分就會被忽略;
-
如果異常匹配于 except 關鍵字后面指定的異常類型,就執行對應的except子句,然后繼續執行 try 語句之后的代碼;
-
如果發生了一個異常,在 except 子句中沒有與之匹配的分支,它就會傳遞到上一級 try 語句中;
-
如果最終仍找不到對應的處理語句,它就成為一個 未處理異常,終止程序運行,顯示提示信息。
try/except 語句還可以帶有一個 else、finally子句,示例如下:
def getNum(n):try:print('try --> ',10 / n)except ZeroDivisionError:print('except --> Error: ZeroDivisionError argument.')else:print('else -->')finally:print('finally -->')'''
1.調用:getNum(0)
輸出結果:
except --> Error: ZeroDivisionError argument.
finally -->2.調用:getNum(1)
輸出結果:
try --> 10.0
else -->
finally -->
'''
其中,else 子句只能出現在所有 except 子句之后,只有在沒有出現異常時執行;finally 子句放在最后,無論是否出現異常都會執行。
2.3 拋出異常
使用 raise 語句允許強制拋出一個指定的異常,要拋出的異常由 raise 的唯一參數標識,它必需是一個異常實例或異常類(繼承自 Exception 的類),如:
raise NameError('HiThere')
2.4 自定義異常
正常來說,Python 提供的異常類型已經滿足我們的使用了,但是有時候我們有定制性的需求,我們可以自定義異常類,繼承自 Error 或 Exception 類就可以了,看個例子:
# 自定義異常類 MyExc
class MyExc(Exception): #繼承Exception類def __init__(self, value):self.value = valuedef __str__(self):if self.value == 0:return '被除數不能為0'
# 自定義方法
def getNum(n):try:if n == 0:exc = MyExc(n)print(exc)else:print(10 / n)except:pass
'''
1.調用 getNum(1),輸出結果為:
10.02.調用 getNum(0),輸出結果為:
被除數不能為0
'''
在這個自定義的異常例子中,當參數 n 不為 0 時,則正常,當 n 等于 0,則拋出異常,自定義異常在實際應用中很少用到,了解即可。