<style>
.red {
color: red;
}
.blue{
color: blue;
}
.green{
color: green;
}
</style>
# 例外處理
## 9-1 認識例外
### 常見的錯誤類型:
1. **語法錯誤**(**syntax error**)
2. **執行期間錯誤**(**runtime error**)
3. **邏輯錯誤**(**logic error**)
- 當Python程式發生錯誤時,系統會丟出一個例外(exception)
- Traceback指的是此錯誤訊息是追朔到函式呼叫所發生的
### 例外的類型
1. ImportError: 匯入module指令發生錯誤,可能是模型路徑或名稱有錯誤
2. IndexError: 索引運算子的範圍錯誤
3. MemoryError: 記憶體空間不足
4. NameError: 名稱尚未定義
```
>>> def greet(name):
>>> print("Hello, " + name + "!")
>>> greet("Alice")
>>> print(age)
Traceback (most recent call last):
File "example.py", line 5, in <module>
print(age)
NameError: name 'age' is not defined
```
5. OverflowError: 溢位。指的是算術運算的結果太大,超過能夠表示的範圍
6. RuntimeError: 執行期間錯誤
7. SyntaxError: 語法錯誤
8. IndentationError: 縮排錯誤
9. SystemError: 直譯器(interpreter)發生內部錯誤
10. TypeError: 將運算或函式套用到型別錯誤的物件
```
>>> def add_numbers(a, b):
>>> return a + b
>>> result = add_numbers(5, "10")
>>> print(result)
Traceback (most recent call last):
File "example.py", line 4, in <module>
result = add_numbers(5, "10")
File "example.py", line 2, in add_numbers
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
```
11. ValueError: 內建運算或函式接收到型別正確但值錯誤的引述
```
>>> def calculate_square_root(num):
>>> if num < 0:
>>> raise ValueError("Cannot calculate square root of a negative number.")
>>> return num ** 0.5
>>> result = calculate_square_root(-9)
>>> print(result)
Traceback (most recent call last):
File "example.py", line 6, in <module>
result = calculate_square_root(-9)
File "example.py", line 3, in calculate_square_root
raise ValueError("Cannot calculate square root of a negative number.")
ValueError: Cannot calculate square root of a negative number.
```
12. ZeroDivisionError: 除以0的錯誤運算
13. ConnectError、ConnectAbortedError、ConnectRefusedError、ConnectionResetError: 連線錯誤、連線失敗、連線被拒絕、連線重設
14. FileExistsError: 企圖要建立已經存在的檔案或目錄,會導致檔案重複
15. FileNotFoundError: 要求的檔案或目錄不存在或找不到
16. TimeoutError: 系統函式逾時
### 例外的處理
- 程式的執行是會經常遇到例外的發生,一旦遇到例外則整個程式會直接停止。上述這種情況其是不是我們想遇到的
- 比較理想的情況是,若遇到例外則去捕捉系統丟出的例外,然後根據系統丟出的例外叫使用者進行調整。此時整個程式仍然還在執行中
- 舉個例子: 若要求User輸入檔案位置,但User輸入錯誤。此時系統一定會丟出FileNotFoundError這個例外,而整個程式會終止。因此需要使用try...except來幫我們捕捉例外,然後使得程式在不停止的情況下,可以讓User重新輸入
## 9-2 try...except
```
>>> while True:
>>> try:
>>> x = eval(input("請輸入被除數 x: "))
>>> y = eval(input("請輸入除數 y: "))
>>> z = x / y
>>> except ZeroDivisionError:
>>> print("除數不可以為0,請重新輸入!")
# 這裡使用到指派變數給e1
# 透過e1的args屬性取得例外的訊息並且印出
>>> except Exception as e1:
>>> print("發生錯誤:", e1.args)
>>> print("請重新輸入!")
>>> else:
>>> print("沒有捕捉到例外! x 除以 y = ", z)
>>> break
>>> finally:
>>> print("程式執行完畢,離開try...except區塊")
# else, finally為選擇性statement,可以指定或省略
# finally statement可以用來清除錯誤或收尾
```
- 若except後面不加任何的exceptionType,則預設型別為<span class='red'>BaseException,所有的例外都是繼承自這個型別</span>
### 自行丟出例外
```
>>> raise NameError("Hello")
ERROR!
Traceback (most recent call last):
File "<main.py>", line 1, in <module>
NameError: Hello
```
```
>>> try:
>>> raise NameError("Hello")
>>> except NameError:
>>> print("捕捉到NameError!")
捕捉到NameError!
```
### 例外處理的時機
- <span class='red'>當程式需要與外部交換資料時</span>: 存取檔案、透過網路連線執行某些動作、開啟資料庫等
- 透過加入例外處理,可以排除或顯示相關錯誤訊息來提醒使用者