Python3 try-except、raise和assert解析

1、說明

關於異常捕獲try-except:在學java的時候就被教育異常捕獲也是java相對c的一大優勢,幾年下來多少也寫了些代碼,但異常捕獲總只得其形未得其神,在本身這只是讓發生錯誤的程序在沒必要要終止時不終止而已。html

關於主動拋出異常raise:前段時間看到robot framework判斷測試用例運行失敗,是監控本身使用raise主動拋出的異常,這纔有了主動拋出異常的概念。java

關於斷言assert:前段時間寫了個模糊測試工具,而後發現不少能夠致使宕機的問題,開發排查後說是新加的斷言致使的問題;當時對斷言並不太清楚,他們修復問題後也沒深刻追究。python

其實這裏最主要是說,瞭解以後發現,try-except、raise和assert其實有至關大的關係,有必要記一記。express

 

2、異常捕獲try-except

異常捕獲沒有不少說的,各語言意思都差很少只是書寫格式有點區別,咱們直接上示例:函數

def testTryExcept():
    try:
        file_obj = open('myfile.txt')
        str_var = file_obj.readline()
        int_var = int(str_var.strip())
    # 若是檢測到是OSError類異常,進行如下處理
    # OSError as err表示給當前捕獲到的OSError異常起別名爲err;名字叫什麼能夠是隨意的
    except OSError as err:
        print(f"OS error: {err}")
    # 若是不是OSError檢測到是ValueError,進行如下處理
    except ValueError:
        print("Could not convert data to an integer.")
    # 若是既不是OSError也不是ValueError而是其餘異常,進行如下處理
    # Exception as e表示給當前捕獲到的異常起別名爲e;名字叫什麼能夠是隨意的
    # 若是不須要打印e,那麼Exception as e這部分可省略
    # 我本身而言,不會捕獲具體的異常類型,即不會像上面同樣單獨捕獲OSError和ValueError,就只寫下邊這麼一個except就完了
    except Exception as e:
        print(f"Unexpected error: {e}")
    # 不論是否發生異常,finally部分都會執行
    # 對於異常捕獲而言,finally部分常常能夠沒有,至少一直以來我都不怎麼寫
    finally:
        file_obj.close()

 

3、主動拋出異常raise

在上面的try-except中咱們都是被動等待異常出現而後進行捕獲----事實上這些被動等待的異常本質上也是庫函數使用raise主動拋出的----咱們徹底可使用raise主動拋出異常,進一步說咱們可使用raise拋出本身定義的異常。工具

主動拋出異常的好處,一是能夠拋出在語法上不被認爲是異常但在功能上咱們認爲是異常的狀況(如用戶名密碼錯誤等),二是能夠自定義本身的異常報錯語句更方便異常的定位和排查。測試

注意,主動拋出的異常扔是異常,因此仍能夠用try-except來捕獲。ui

# 自定義的異常類都要繼承Exception類,至少是間接繼承Exception類
class PasswordException(Exception):
    # 在init方法中定義一個password變量
    def __init__(self,password):
        self.password = password

    def __str__(self):
        return repr(self.password)

def testRaise():
    # 主動拋出異常示例
    try:
        username = input("please enter your username:")
        # 輸入的用戶名不是admin就拋出異常Exception
        if username != "admin":
            raise Exception(f"maybe your privilege is not enough: {username}")
    # 能夠看到打印的是咱們自定義的異常語句
    except Exception as e:
        print(f"{e}")

    # 主動拋出自定義異常示例
    try:
        password = input("please enter your password:")
        # 輸入的密碼不是123456就拋出自定的的PasswordException異常
        if password != "123456":
            raise PasswordException(password)
    # 咱們自定義的異常有password變量,因此咱們能夠直接選擇把變量打印出來
    except PasswordException as e:
        print(f"PasswordException: {e.password}")

if __name__ == "__main__":
    testRaise()

 

4、斷言assert

4.1 assert本質討論

更多參見官方文檔:https://docs.python.org/3/reference/simple_stmts.html#the-assert-statementspa

assert使用形式以下:debug

assert expression ["," expression]

若是隻接一個表達示,那至關於以下:

if __debug__:
    if not expression: raise AssertionError

若是接兩個表達示,那至關於以下:

if __debug__:
    if not expression1: raise AssertionError(expression2)

其中涉及的__debug__和AssertionError以下:

__debug__:若是程序運行時不帶-O參數,則爲True;反之則爲False。

AssertionError:就是一個繼承Exception類的異常類,其源代碼在builtins.py中,以下圖所示

因此,本質上,assert就是raise的一個宏定義;當前緊接的好個表達示不爲True時,就拋出異常。

 

4.2 assert的使用

assert常常用於參數被使用前的檢查操做,若是檢查未經過則直接拋出異常及早發現錯誤,避免明顯錯誤的參數還被日後傳遞。

注意,因爲assert本質上仍是raise,因此同樣可使用try-except捕獲,而不是說斷言錯誤程序就必定會終止。

def testAssert():
    try:
        int_var = int(input("please enter a positive number:"))
        # 若是輸入的數值不大於0,斷言失敗,拋出異常
        assert int_var > 0
    except:
        print(f"sorry, please enter a positive number")
    print(f"what you enter is: {int_var}")

if __name__ == "__main__":
    testAssert()

 

參考:

https://www.runoob.com/python3/python3-errors-execptions.html

相關文章
相關標籤/搜索