簡體   English   中英

bare except 和指定特定異常之間的區別

[英]Difference between bare except and specifying a specific exception

在這段代碼中,我可以編寫一個簡單的 except 子句,而不用在它前面寫 Exception。 我的意思是最后一行可能是這樣的:

except:
  print('Hit an exception other than KeyError or NameError!')

在 except 子句前寫 Exception 有什么意義?

try:
    discounted_price(instrument, discount)
except KeyError:
    print("There is a keyerror in your code")
except NameError:
    print('There is a TypeError in your code')
except Exception:
    print('an exception occured')

我嘗試編寫一個不帶 Exception 關鍵字的 except 子句,但效果相同。

謝謝你們的回答。 我知道捕捉特定錯誤的意義所在。 如果我想問得更清楚,兩個子句有什么區別:

except Exception:
    print('an exception occured')

except :
    print('an exception occured')

指定異常的要點是只有那個異常會被捕獲,如果你沒有指定任何異常,那么所有錯誤和異常都將被捕獲,可能會掩蓋錯誤。

例如,假設我想讀取一個文件(如果它存在)或以其他方式向用戶打印一條消息,我可以這樣寫:

try:
    with ope("example.txt", "r") as f:
        print(f.read())
except:
    print("File not found")

但是,雖然這段代碼運行良好且沒有引發任何異常,但這段代碼永遠不會讀取該文件,即使它存在!!!

這是因為我寫了ope而不是open並且NameError被我的 bare except捕獲,如果我以正確的方式寫except

try:
    with ope("example.txt", "r") as f:
        print(f.read())
except FileNotFoundError:
    print("File not found")

現在我可以正確調試我的代碼了:

Traceback (most recent call last):
  File "/home/riccardo/types.py", line 4, in <module>
    with ope("example.txt", "r") as f:
NameError: name 'ope' is not defined

只需添加@Caridorc 提供的答案,通過分別指定每個錯誤,您可以在出現異常時運行與該錯誤相關的特定錯誤處理代碼。 例如,如果該文件不存在,您可以打印消息。 但是,如果由於您錯誤輸入了 g 而不是 f 而導致打印失敗,您可以打印一條消息,說明該變量未被識別(用於單獨錯誤捕獲的單獨代碼)。 例如:

g = 100 # Unrelated variable declared previously
try:
    with open("example.txt", "r") as f:
        x=print(f.read())

except FileNotFoundError:
    print("File not found")
except AttributeError:
    print("Reading wrong variable")
except Exception as e:
    print("Unknown Error", e)

還要注意except Exception as e:的最后一個異常。 這與except:相同,但允許您處理所有其他不適合先前捕獲的錯誤並檢索 e - 編譯器生成的錯誤消息。 except:except Exception:在執行方面實際上沒有區別

考慮代碼:

a = 5
b = 0
x = a / b

執行此操作會提醒您,您已嘗試將浮點數除以零,但這會使您的代碼崩潰。

現在考慮:

a = 5
b = 0
try:
    x = a / b
except: # or 'except Exception:'
    print("An exception was raised")

這將引發一個異常,該異常通過打印一條發生錯誤的消息來處理。 您的代碼不會崩潰,但您不知道如何正確處理代碼,因為您不知道異常是什么,只是發生了一個異常。

現在考慮:

a = 5
b = 0
try:
    x = a / b
except Exception as e:
    print("An exception was raised, generating error", e)

現在您的代碼不會崩潰。 已處理,您知道錯誤是什么。

一個勉強的期望

try:
    ...
except:
    pass

或捕獲任何異常

try:
    ...
except Exception:
    pass

是不好的做法,因為您可能會隱藏錯誤或干擾程序的正常過程。

你應該只捕獲你知道如何處理的異常,你應該讓它傳播的所有其他內容。

舉個例子:

隱藏錯誤:它可以在您的代碼中隱藏一些拼寫錯誤,因為 Caridorc 示例顯示讓您認為您遇到的問題與實際問題不同

干擾正常過程:您可以使它成為一個意外的無法殺死的程序,或者通過丟棄代碼的另一部分所期望的異常來妨礙程序的正常過程。

比如說

while True:
    try: 
        print("running")
    except:
        print("I'm immortal muahahaha")

這段代碼現在你不能用你通常的 control-z 停止(control-z throw 和 KeyboardInterrupt exception into your program)所以你現在需要關閉整個解釋器/用任務管理員殺死它只是為了停止它,並且如果這是無意的,那么您只是引入了一個新錯誤,並且根據您的操作,它可能是災難性的。

為了說明它的災難性程度,請考慮以下假設情況:假設您為醫療設備制作了如此良性的 function 並且您將這樣的東西放在

try: 
    ...
except:
    print("some error happens")

現在碰巧的是,當你的一段代碼正在運行時,一個 HeartAttack 異常被引發,你抓住它並忽略這段代碼就可以了,好吧,就是這樣,這就是這個設備是起搏器的轉折點......好吧,恭喜你剛剛殺了那個可憐的家伙。

這就是為什么你應該只捕獲你知道如何處理的異常,你讓它通過的所有其他東西,並希望沿線的人知道如何處理它,就像上面的例子一樣,你和你的代碼片段不我知道如何處理 HeartAttack,但起搏器會,起搏器會調用您的代碼讓它處理它......


對於一個不那么極端的例子,考慮這個簡單的代碼

def get_number_from_user():
    while True:
        try:
            return int(input("write a number: "))
        except:
            print("not a valid number try again")

如果你的用戶已經完成了你的程序,而這恰好是正在運行的東西,他/她可能想像你通常對任何程序所做的那樣用 control-z 殺死它,但它會發現它不起作用,正確的這里的方法是捕獲我們知道如何在這種情況下處理的錯誤,即 ValueError,其他一切都不是這個 function 業務

def get_number_from_user():
    while True:
        try:
            return int(input("write a number: "))
        except ValueError:
            print("not a valid number try again")

你還問了兩者之間的區別

try:
    ...
except:
    pass

和這個

try:
    ...
except Exception:
    pass

不同之處在於,一個簡單的 except 可以捕獲任何和所有類型的異常,在 python 中是位於異常層次結構頂部的 BaseException 或從 BaseException 繼承的任何異常,而except Exception將僅捕獲Exception本身或繼承自的任何異常它(同樣適用於你放在那里的任何特定異常),這個小區別允許使一些異常比其他異常更特殊,比如前面提到的 KeyboardInterrupt 從 BaseException 而不是 Exception 繼承,並且用於表示用戶想要終止這個程序,所以你應該這樣做,這個區別基本上是為了讓新程序員在使用except Exception時不會搬起石頭砸自己的腳

在except子句前寫“Exception”的目的是捕獲代碼中所有可能出現的異常。 通過指定“Exception”,您告訴解釋器處理可能引發的任何類型的異常。 except 子句中指定的異常越具體,異常的處理就越有針對性。 例如,如果您只想處理“KeyError”異常,您可以在 except 子句中明確指定,如第一個示例所示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM