Python?錯誤處理的最佳實(shí)踐
1. 什么是異常?
異常(Exception)就是程序運(yùn)行時發(fā)生的錯誤,比如試圖打開一個不存在的文件、除以零或者輸入了非法數(shù)據(jù)。Python 會拋出異常來告訴你“嘿,這里出問題了!”。如果不處理,程序會直接崩潰,打印一堆錯誤信息(就是 traceback)。
異常處理的核心是用代碼“捕獲”這些錯誤,防止程序崩掉,還能給用戶友好的提示。
2. 常見的 Python 異常類型
Python 內(nèi)置了很多異常類型,了解它們能幫你更好地處理問題。以下是一些常見的異常:
ZeroDivisionError
:除以零時觸發(fā)。FileNotFoundError
:試圖打開不存在的文件。ValueError
:函數(shù)接收到不合適的參數(shù),比如把字符串傳給int()
。TypeError
:類型錯誤,比如試圖把字符串和整數(shù)相加。IndexError
:列表索引超出范圍。KeyError
:訪問字典中不存在的鍵。
這些異常都是 Python 的內(nèi)置類,繼承自 Exception
類。你可以在代碼中捕獲它們。
3. 基本的 try-except 結(jié)構(gòu)
Python 用 try-except
塊來處理異常?;舅悸肥牵喊芽赡艹鲥e的代碼放進(jìn) try
塊,如果出錯了,就跳到 except
塊執(zhí)行。
來看個簡單的例子:
try: num = int(input("請輸入一個數(shù)字: ")) result = 10 / num print(f"10 除以 {num} 等于 {result}") except: print("出錯了!可能輸入了非法數(shù)字或除以零。")
運(yùn)行這段代碼:
- 如果用戶輸入一個合法數(shù)字,比如
5
,程序會打印10 除以 5 等于 2.0
。 - 如果輸入了非數(shù)字(比如
"abc"
)或0
,程序會跳到except
塊,打印錯誤提示,而不會崩潰。
這個 except
是個“通吃”模式,捕獲所有異常。但最好別這樣用,因?yàn)槟悴恢谰唧w出了啥問題。接下來我們改進(jìn)它。
4. 捕獲特定異常
與其捕獲所有異常,不如只捕獲你關(guān)心的特定異常類型。這樣能更精準(zhǔn)地處理問題。Python 允許在 except
后指定異常類型。
改寫上面的例子:
try: num = int(input("請輸入一個數(shù)字: ")) result = 10 / num print(f"10 除以 {num} 等于 {result}") except ValueError: print("請輸入一個合法的數(shù)字!") except ZeroDivisionError: print("不能除以零!")
現(xiàn)在:
- 如果輸入
"abc"
,會觸發(fā)ValueError
,打印“請輸入一個合法的數(shù)字!”。 - 如果輸入
0
,會觸發(fā)ZeroDivisionError
,打印“不能除以零!”。 - 其他異常(比如
KeyboardInterrupt
)不會被捕獲,程序會照常報錯。
你可以捕獲多個異常,也可以把異常對象保存下來,查看具體錯誤信息:
try: num = int(input("請輸入一個數(shù)字: ")) result = 10 / num except ValueError as e: print(f"輸入錯誤: {e}") except ZeroDivisionError as e: print(f"除零錯誤: {e}")
這里 as e
把異常對象存到變量 e
,可以打印更詳細(xì)的錯誤信息。
5. 使用 else 和 finally
try-except
還有兩個好用的伙伴:else
和 finally
。
else
:如果try
塊沒出錯,就執(zhí)行else
塊。適合放那些依賴try
塊成功的代碼。finally
:不管try
塊有沒有出錯,finally
塊都會執(zhí)行。常用來做清理工作,比如關(guān)閉文件。
來看個例子:
try: num = int(input("請輸入一個數(shù)字: ")) result = 10 / num except ValueError: print("請輸入合法數(shù)字!") except ZeroDivisionError: print("不能除以零!") else: print(f"計(jì)算成功!結(jié)果是: {result}") finally: print("程序結(jié)束,清理完成!")
運(yùn)行效果:
- 輸入
5
:打印“計(jì)算成功!結(jié)果是: 2.0”和“程序結(jié)束,清理完成!”。 - 輸入
"abc"
:打印“請輸入合法數(shù)字!”和“程序結(jié)束,清理完成!”。 - 輸入
0
:打印“不能除以零!”和“程序結(jié)束,清理完成!”。
finally
特別適合確保資源被正確釋放,比如:
try: file = open("data.txt", "r") content = file.read() except FileNotFoundError: print("文件沒找到!") else: print(f"文件內(nèi)容: {content}") finally: try: file.close() print("文件已關(guān)閉") except NameError: print("文件從未打開,無需關(guān)閉")
這里 finally
確保文件被關(guān)閉,即使文件沒找到(導(dǎo)致 file
未定義)也能安全處理。
6. 拋出異常
有時候你想主動拋出異常,比如檢查到用戶輸入不符合要求。可以用 raise
關(guān)鍵字拋出異常。
例子:
def divide(a, b): if b == 0: raise ZeroDivisionError("除數(shù)不能為零!") return a / b try: result = divide(10, 0) except ZeroDivisionError as e: print(f"錯誤: {e}")
運(yùn)行會打印“錯誤: 除數(shù)不能為零!”。你可以用 raise
拋出任何內(nèi)置異常,或者直接用 raise Exception("自定義消息")
。
還可以“重新拋出”異常:
try: num = int(input("請輸入一個數(shù)字: ")) except ValueError as e: print(f"輸入錯誤: {e}") raise # 重新拋出原異常
這樣會在處理完錯誤后,繼續(xù)把異常拋給上層調(diào)用者。
7. 自定義異常
當(dāng)內(nèi)置異常不夠用時,你可以定義自己的異常類。自定義異常通常繼承自 Exception
類。
例子:
class CustomValueError(Exception): """自定義異常,用于值不符合要求""" pass def check_age(age): if age < 0 or age > 150: raise CustomValueError("年齡必須在0到150之間!") return age try: age = check_age(200) except CustomValueError as e: print(f"錯誤: {e}")
運(yùn)行會打印“錯誤: 年齡必須在0到150之間!”。自定義異常讓代碼更清晰,尤其在復(fù)雜項(xiàng)目中。
8. 錯誤處理的最佳實(shí)踐
最后,分享一些寫錯誤處理代碼的建議:
- 捕獲特定異常:別用“通吃”的
except
,盡量指定具體的異常類型。 - 提供清晰的錯誤信息:用戶看到錯誤時,應(yīng)該知道問題出在哪,怎么解決。
- 用 else 和 finally 合理組織代碼:
else
放依賴try
成功的邏輯,finally
放清理工作。 - 別濫用異常:異常是用來處理“異常情況”的,別用它來控制正常流程(比如代替
if
判斷)。 - 記錄錯誤日志:在實(shí)際項(xiàng)目中,用
logging
模塊記錄異常,方便調(diào)試。
例子(帶日志):
import logging logging.basicConfig(level=logging.ERROR, filename="app.log") try: num = int(input("請輸入一個數(shù)字: ")) result = 10 / num except ValueError as e: logging.error(f"輸入錯誤: {e}") print("請輸入合法數(shù)字!") except ZeroDivisionError as e: logging.error(f"除零錯誤: {e}") print("不能除以零!") else: print(f"結(jié)果: {result}") finally: print("程序結(jié)束!")
這個例子會把錯誤記錄到 app.log
文件,方便排查問題。
到此這篇關(guān)于Python 錯誤處理詳解的文章就介紹到這了,更多相關(guān)Python 錯誤處理詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
執(zhí)行Django數(shù)據(jù)遷移時報 1091錯誤及解決方法
這篇文章主要介紹了執(zhí)行Django數(shù)據(jù)遷移,報錯 1091,需要的朋友可以參考下2019-10-10Selenium獲取登錄Cookies并添加Cookies自動登錄的方法
這篇文章主要介紹了Selenium獲取登錄Cookies并添加Cookies自動登錄的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Python簡單獲取網(wǎng)卡名稱及其IP地址的方法【基于psutil模塊】
這篇文章主要介紹了Python簡單獲取網(wǎng)卡名稱及其IP地址的方法,結(jié)合實(shí)例形式分析了Python基于psutil模塊針對本機(jī)網(wǎng)卡硬件信息的讀取操作簡單使用技巧,需要的朋友可以參考下2018-05-05在Python中預(yù)先初始化列表內(nèi)容和長度的實(shí)現(xiàn)
今天小編就為大家分享一篇在Python中預(yù)先初始化列表內(nèi)容和長度的實(shí)現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11修改Python的pyxmpp2中的主循環(huán)使其提高性能
這篇文章主要介紹了修改Python的pyxmpp2中的主循環(huán)使其提高性能,pyxmpp2是Python中使用需XMPP協(xié)議的一個常用工具,要的朋友可以參考下2015-04-04Python 編碼規(guī)范(Google Python Style Guide)
本項(xiàng)目并非 Google 官方項(xiàng)目, 而是由國內(nèi)程序員憑熱情創(chuàng)建和維護(hù),對于想學(xué)習(xí)python的朋友可以參考一下2018-05-05Python使用pytorch動手實(shí)現(xiàn)LSTM模塊
這篇文章主要介紹了Python使用pytorch動手實(shí)現(xiàn)LSTM模塊,LSTM是RNN中一個較為流行的網(wǎng)絡(luò)模塊。主要包括輸入,輸入門,輸出門,遺忘門,激活函數(shù),全連接層(Cell)和輸出2022-07-07