『無為則無心』Python函式 — 38、Python中的異常

繁華似錦Fighting 發表於 2022-01-26
Python

1、異常概念

定義:程式在執行過程當中,不可避免的會出現一些錯誤,可能經常看到的報錯資訊,例如:NameErrorTypeErrorValueError等,這些都是異常。

程式執行過程中,一旦出現異常將會導致程式立即終止,異常以後的程式碼全部都不會執行。所以當Python程式發生異常時,我們需要捕獲並處理異常,否則程式就會終止執行,影響程式的正常執行。

2、瞭解異常

當檢測到一個錯誤時,直譯器就無法繼續執行了,會出現一些錯誤的提示到控制檯,這就是所謂的"異常"。

例如:以r方式開啟一個不存在的檔案,就會丟擲異常,我們在控制檯中就能夠看到。

open('test.txt', 'r')

image

像上面這種情況,我們在編寫程式碼的時候,我們不確定一個語句是否一定會正確執行,這個時候就可以把這句可能出現的問題的程式碼,放入到異常語句中。

因為異常語句會嘗試執行一行或一段可能發生錯誤的程式碼,萬一發生錯誤可以執行另外一行或一段一定可以執行的程式碼,從而替代有錯誤的程式碼。以達到讓程式不報錯,可以繼續向下執行程式。

總結:

Python程式執行時出現異常,目的並不是讓我們的程式直接終止。

而是Python是希望在出現異常時,我們可以編寫程式碼來對異常進行處理。

3、異常的寫法

(1)語法

try:
    可能發生錯誤的程式碼
except:
    如果出現異常執行的程式碼(出現錯誤以後的處理方式)

(2)快速體驗

需求:嘗試以r模式開啟檔案,如果檔案不存在,則以w方式開啟。

try:
    f = open('test.txt', 'r')
except:
    f = open('test.txt', 'w')

(3)捕獲指定異常

1)語法

try:
    可能發生錯誤的程式碼
except 異常型別:
    如果捕獲到該異常型別執行的程式碼

說明:如果我們執行的程式碼有錯誤,且錯誤型別和except指定的異常型別一致,則執行匹配型別異常下定義的程式碼。

總結:

  • 如果except後不跟任何的內容,則此時它會捕獲到所有的異常。
  • 如果在except後跟著一個異常的型別,那麼此時它只會捕獲該型別的異常。

2)體驗

"""
需求:嘗試執行列印num,捕獲異常型別NameError,
如果捕獲到這個異常型別,執行列印:你的變數沒有被定義
"""
# 結果:你的變數沒有被定義
try:
    print(num)
except NameError:
    print('你的變數沒有被定義')

注意:

  1. 如果嘗試執行的程式碼的異常型別和要捕獲的異常型別不一致,則無法捕獲異常。
  2. 一般try下方只放一行嘗試執行的程式碼。

3)捕獲多個指定異常。

有時候我們編寫程式碼的時候,並不確定一行程式碼可能丟擲哪種異常型別,可能就會多寫幾種異常型別。

當捕獲多個異常時,可以把要捕獲的異常型別的名字,統一放到except後,並使用元組的方式進行書寫。

try:
    print(1/0)
except (NameError, ZeroDivisionError):
    print('有錯誤')

只要嘗試執行的異常程式碼,所丟擲來的異常型別,和except後定義在元組中的任一異常型別相匹配,都能被捕獲到。

不同型別的異常型別也可以分開寫,如下:

try:
    print(10/0)
except NameError:
    print('出現 NameError 異常')
except ZeroDivisionError:
    print('出現 ZeroDivisionError 異常')
except IndexError:
    print('出現 IndexError 異常')

4)何為異常型別何為異常描述資訊。

在控制檯檢視的異常資訊中,如NameError: name 'num' is not defined

冒號前NameError,顯示的就是異常型別。

冒號後name 'num' is not defined,顯示的就是異常描述資訊。

5)捕獲異常描述資訊。

try:
    print(num)
except (NameError, ZeroDivisionError) as result:
    print(result)

# 或者
try:
    print(10/0)
except NameError as e:
    print('異常型別',e)
except ZeroDivisionError as e:
    print('異常型別',e)
except IndexError as e:
    print('異常型別',e)

as是一個關鍵字,as關鍵字後的變數就是捕獲到的異常的描述資訊,變數名是可以自定義的。

6)捕獲所有異常。

Exception是所有程式異常類的父類,所以如果except後跟的是Exception,也會捕獲到所有的異常。

# 1.捕獲所有異常
try:
    print(num)
except Exception:
    print("捕獲異常了")

# 或者不寫Exception
try:
    print(num)
except:
    print("捕獲異常了")

# 2.捕獲所有異常資訊
try:
    print(num)
except Exception as result:
    print(result)

(4)異常中的else

else表示的是如果沒有異常要執行的程式碼。

try:
    print(1)
except Exception as result:
    print(result)
else:
    print('我是else,是沒有異常的時候執行的程式碼')

(5)異常中的finally

finally表示的是,無論是否異常都要執行的程式碼。也就是說,不管前邊程式碼是否正確執行,都必須只要執行的程式碼,就寫在finally中。例如關閉檔案。

try:
    f = open('test.txt', 'r')
except Exception as result:
    f = open('test.txt', 'w')
else:
    print('沒有異常,真開心')
finally:
    # 一般用於關閉所有開啟的資源
    f.close()

(6)總結

異常處理的完整結構,如下所示:

try語句
    try:
        程式碼塊(可能出現錯誤的語句)
    except 異常型別 as 異常名:
        程式碼塊(出現錯誤以後的處理方式)
    except 異常型別 as 異常名:
        程式碼塊(出現錯誤以後的處理方式)
    except 異常型別 as 異常名:
        程式碼塊(出現錯誤以後的處理方式)
    else:
        程式碼塊(沒出錯時要執行的語句)
    finally:
        程式碼塊(該程式碼塊總會執行)

說明:

  • try是必須寫的,可以將可能出錯的程式碼放入到try語句中,這樣如果程式碼沒有錯誤,則會正常執行。如果出現錯誤,則會執行expect子句中的程式碼,這樣我們就可以通過程式碼來處理異常, 避免因為一個異常導致整個程式的終止 。
  • else語句有沒有都行。
  • exceptfinally至少有一個 。