# Try-Except
## Sprout Py2021
@robert1003
----
想讓程式在壞掉後繼續跑?
----
```python=
# 我就 4 要除 0
print(1 / 0)
```
```
ZeroDivisionError Traceback (most recent call last)
<ipython-input-1-3ec96714f820> in <module>
----> 1 print(1 / 0)
ZeroDivisionError: division by zero
```
----
怎麼對付他呢?
---
## Exception
----
* 一種特殊的 Class
* 前面的 `ZeroDivisionError` 就是其中一種
* 所有的 Exception Class 們都是 Base Exception Class 的子孫
* [所有的 Base Exception Class](https://docs.python.org/3/library/exceptions.html#base-classes)
---
## try-except
----
抓住所有的 Exception
```python=
try:
你的 code
except:
你的 code 爛掉就會跑來這裡
```
----
ValueError
```python=
try:
[].index(1)
except:
print('1 not in list')
```
----
ZeroDivisionError
```python=
try:
print(1 / 0)
except:
print('cannot divide by 0')
```
----
自己 try try 看!想辦法寫個爛掉的 code
----
Question:可以處理排版錯誤嗎?
```
try:
1 / 0
1 / 0
except Exception as e:
print(e, type(e))
```
```
IndentationError: unexpected indent
```
---
## try-except-except
想抓住特定的錯誤?
----
我只想把除零的 case 抓住,其他的讓他自然噴錯就好
```python=
try:
你的 code
except 你想處理的Exception的名字:
你想處理的方法
except 你想處理的另一個Exception的名字:
你想處理的方法
...
```
----
```python=
try:
print(1 / 0) # 會被抓住
except ZeroDivisionError:
print('cannot divide by 0')
```
----
```python=
try:
print(1 / 0) # 會被抓住
[].index(0) # 不會被抓住
except ZeroDivisionError:
print('cannot divide by 0')
```
----
Question:會印出什麼?
```python=
try:
print(1 / 0) # ZeroDivisionError, 會被抓住
[].index(0) # ValueError, 會被抓住
[].find(0) # AttributeError, 不會被抓住
except ZeroDivisionError:
print('cannot divide by 0')
except ValueError:
print('0 not in list')
```
----
try-except-except 會執行到第一個錯誤為止
---
## try-except-finally
不管有沒有發生錯誤都要執行的東西
----
finally
```python=
try:
你的 code
except 處理其中一種 Exception:
處理的 code
finally:
無論如何都會跑的 code
```
----
```python=
try:
print(1 / 0)
except ZeroDivisionError:
print('zero division error')
finally:
print('finally')
```
----
跟這個差在哪?
```python=
try:
print(1 / 0)
except ZeroDivisionError:
print('zero division error')
print('finally')
```
----
你有 Exception 沒處理到的時候就會有差
```python=
try:
[].index(0) # 不會被抓住
except ZeroDivisionError:
print('zero division error')
finally:
print('finally')
```
---
## raise
誰說自己不能生錯誤呢
----
自己噴錯
```python=
raise 你想噴的Exception instance
```
----
亂噴錯
```python=
x = int(input())
if x == 5:
raise Exception("I don't like 5, go away")
```
----
亂噴錯2
```python=
x = int(input())
if x == 5:
raise ZeroDivisionError("I don't like 5, go away")
```
----
小提醒:自己寫扣的時候亂噴錯沒關係,但跟別人合作的時候不能這樣,因為別人會看不懂為什麼爛掉
----
小練習:試試看自己 raise 一個 Exception 然後用上面教的 try-catch 把他抓住
---
## custom exception
自己寫Exception Class
----
* 還記得前面說的嗎?
* 「所有的 Exception Class 們都是 Base Exception Class 的子孫」
----
```python=
class 你的Exception名字(Exception): # 繼承 Exception 這個 Base exception class
pass
```
----
「我不喜歡5」Exception
```python=
class IDontLikeFiveError(Exception):
pass
x = int(input())
if x == 5:
raise IDontLikeFiveError("我不喜歡5")
```
----
小提醒:
1. Class 名稱通常都要首字母大寫
2. Exception Class 名稱通常都要 "Error" 結尾
----
小練習:自己建立一個 Exception Class 然後 raise 他
----
客製化自己的 Exception Class
```python=
class IDontLikeError(Exception):
def __init__(self, what, reason):
self.what = what
self.reason = reason
def __str__(self):
return "I don't like {} because {}".format(self.what, self.reason)
x = int(input())
raise IDontLikeError(x, "我就4不喜歡")
```
----
小練習:客製化自己剛剛的 Exception Class,讓他的 error message 都加上一個 prefix "我就4不喜歡:"
---
## Q&A
{"metaMigratedAt":"2023-06-16T00:10:31.572Z","metaMigratedFrom":"YAML","title":"Try-Except","breaks":true,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"3d3e812e-7132-40aa-b06f-8f5380bf64d1\",\"add\":11772,\"del\":8086}]"}