Python?錯(cuò)誤處理的最佳實(shí)踐
1. 什么是異常?
異常(Exception)就是程序運(yùn)行時(shí)發(fā)生的錯(cuò)誤,比如試圖打開一個(gè)不存在的文件、除以零或者輸入了非法數(shù)據(jù)。Python 會(huì)拋出異常來(lái)告訴你“嘿,這里出問(wèn)題了!”。如果不處理,程序會(huì)直接崩潰,打印一堆錯(cuò)誤信息(就是 traceback)。
異常處理的核心是用代碼“捕獲”這些錯(cuò)誤,防止程序崩掉,還能給用戶友好的提示。
2. 常見的 Python 異常類型
Python 內(nèi)置了很多異常類型,了解它們能幫你更好地處理問(wèn)題。以下是一些常見的異常:
ZeroDivisionError:除以零時(shí)觸發(fā)。FileNotFoundError:試圖打開不存在的文件。ValueError:函數(shù)接收到不合適的參數(shù),比如把字符串傳給int()。TypeError:類型錯(cuò)誤,比如試圖把字符串和整數(shù)相加。IndexError:列表索引超出范圍。KeyError:訪問(wèn)字典中不存在的鍵。
這些異常都是 Python 的內(nèi)置類,繼承自 Exception 類。你可以在代碼中捕獲它們。
3. 基本的 try-except 結(jié)構(gòu)
Python 用 try-except 塊來(lái)處理異常。基本思路是:把可能出錯(cuò)的代碼放進(jìn) try 塊,如果出錯(cuò)了,就跳到 except 塊執(zhí)行。
來(lái)看個(gè)簡(jiǎn)單的例子:
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
result = 10 / num
print(f"10 除以 {num} 等于 {result}")
except:
print("出錯(cuò)了!可能輸入了非法數(shù)字或除以零。")運(yùn)行這段代碼:
- 如果用戶輸入一個(gè)合法數(shù)字,比如
5,程序會(huì)打印10 除以 5 等于 2.0。 - 如果輸入了非數(shù)字(比如
"abc")或0,程序會(huì)跳到except塊,打印錯(cuò)誤提示,而不會(huì)崩潰。
這個(gè) except 是個(gè)“通吃”模式,捕獲所有異常。但最好別這樣用,因?yàn)槟悴恢谰唧w出了啥問(wèn)題。接下來(lái)我們改進(jìn)它。
4. 捕獲特定異常
與其捕獲所有異常,不如只捕獲你關(guān)心的特定異常類型。這樣能更精準(zhǔn)地處理問(wèn)題。Python 允許在 except 后指定異常類型。
改寫上面的例子:
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
result = 10 / num
print(f"10 除以 {num} 等于 {result}")
except ValueError:
print("請(qǐng)輸入一個(gè)合法的數(shù)字!")
except ZeroDivisionError:
print("不能除以零!")現(xiàn)在:
- 如果輸入
"abc",會(huì)觸發(fā)ValueError,打印“請(qǐng)輸入一個(gè)合法的數(shù)字!”。 - 如果輸入
0,會(huì)觸發(fā)ZeroDivisionError,打印“不能除以零!”。 - 其他異常(比如
KeyboardInterrupt)不會(huì)被捕獲,程序會(huì)照常報(bào)錯(cuò)。
你可以捕獲多個(gè)異常,也可以把異常對(duì)象保存下來(lái),查看具體錯(cuò)誤信息:
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
result = 10 / num
except ValueError as e:
print(f"輸入錯(cuò)誤: {e}")
except ZeroDivisionError as e:
print(f"除零錯(cuò)誤: {e}")這里 as e 把異常對(duì)象存到變量 e,可以打印更詳細(xì)的錯(cuò)誤信息。
5. 使用 else 和 finally
try-except 還有兩個(gè)好用的伙伴:else 和 finally。
else:如果try塊沒(méi)出錯(cuò),就執(zhí)行else塊。適合放那些依賴try塊成功的代碼。finally:不管try塊有沒(méi)有出錯(cuò),finally塊都會(huì)執(zhí)行。常用來(lái)做清理工作,比如關(guān)閉文件。
來(lái)看個(gè)例子:
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
result = 10 / num
except ValueError:
print("請(qǐng)輸入合法數(shù)字!")
except ZeroDivisionError:
print("不能除以零!")
else:
print(f"計(jì)算成功!結(jié)果是: {result}")
finally:
print("程序結(jié)束,清理完成!")運(yùn)行效果:
- 輸入
5:打印“計(jì)算成功!結(jié)果是: 2.0”和“程序結(jié)束,清理完成!”。 - 輸入
"abc":打印“請(qǐng)輸入合法數(shù)字!”和“程序結(jié)束,清理完成!”。 - 輸入
0:打印“不能除以零!”和“程序結(jié)束,清理完成!”。
finally 特別適合確保資源被正確釋放,比如:
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("文件沒(méi)找到!")
else:
print(f"文件內(nèi)容: {content}")
finally:
try:
file.close()
print("文件已關(guān)閉")
except NameError:
print("文件從未打開,無(wú)需關(guān)閉")這里 finally 確保文件被關(guān)閉,即使文件沒(méi)找到(導(dǎo)致 file 未定義)也能安全處理。
6. 拋出異常
有時(shí)候你想主動(dòng)拋出異常,比如檢查到用戶輸入不符合要求??梢杂?nbsp;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"錯(cuò)誤: {e}")運(yùn)行會(huì)打印“錯(cuò)誤: 除數(shù)不能為零!”。你可以用 raise 拋出任何內(nèi)置異常,或者直接用 raise Exception("自定義消息")。
還可以“重新拋出”異常:
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
except ValueError as e:
print(f"輸入錯(cuò)誤: {e}")
raise # 重新拋出原異常這樣會(huì)在處理完錯(cuò)誤后,繼續(xù)把異常拋給上層調(diào)用者。
7. 自定義異常
當(dāng)內(nèi)置異常不夠用時(shí),你可以定義自己的異常類。自定義異常通常繼承自 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"錯(cuò)誤: {e}")運(yùn)行會(huì)打印“錯(cuò)誤: 年齡必須在0到150之間!”。自定義異常讓代碼更清晰,尤其在復(fù)雜項(xiàng)目中。
8. 錯(cuò)誤處理的最佳實(shí)踐
最后,分享一些寫錯(cuò)誤處理代碼的建議:
- 捕獲特定異常:別用“通吃”的
except,盡量指定具體的異常類型。 - 提供清晰的錯(cuò)誤信息:用戶看到錯(cuò)誤時(shí),應(yīng)該知道問(wèn)題出在哪,怎么解決。
- 用 else 和 finally 合理組織代碼:
else放依賴try成功的邏輯,finally放清理工作。 - 別濫用異常:異常是用來(lái)處理“異常情況”的,別用它來(lái)控制正常流程(比如代替
if判斷)。 - 記錄錯(cuò)誤日志:在實(shí)際項(xiàng)目中,用
logging模塊記錄異常,方便調(diào)試。
例子(帶日志):
import logging
logging.basicConfig(level=logging.ERROR, filename="app.log")
try:
num = int(input("請(qǐng)輸入一個(gè)數(shù)字: "))
result = 10 / num
except ValueError as e:
logging.error(f"輸入錯(cuò)誤: {e}")
print("請(qǐng)輸入合法數(shù)字!")
except ZeroDivisionError as e:
logging.error(f"除零錯(cuò)誤: {e}")
print("不能除以零!")
else:
print(f"結(jié)果: {result}")
finally:
print("程序結(jié)束!")這個(gè)例子會(huì)把錯(cuò)誤記錄到 app.log 文件,方便排查問(wèn)題。
到此這篇關(guān)于Python 錯(cuò)誤處理詳解的文章就介紹到這了,更多相關(guān)Python 錯(cuò)誤處理詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Django中modelform組件實(shí)例用法總結(jié)
在本篇文章里小編給大家整理的是關(guān)于Django中modelform組件實(shí)例用法內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)下。2020-02-02
Python實(shí)現(xiàn)對(duì)相同數(shù)據(jù)分箱的小技巧分享
這篇文章主要給大家介紹了關(guān)于Python實(shí)現(xiàn)對(duì)相同數(shù)據(jù)分箱的小技巧,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01
Python+pyaudio實(shí)現(xiàn)音頻控制示例詳解
PyAudio?是語(yǔ)音處理的?Python?庫(kù),提供了比較豐富的功能。本文將利用pyaudio控制指定設(shè)備,實(shí)現(xiàn)錄制音頻、采集音頻流、播放音頻,感興趣的可以了解一下2022-07-07
Python Tkinter 簡(jiǎn)單登錄界面的實(shí)現(xiàn)
今天小編就為大家分享一篇Python Tkinter 簡(jiǎn)單登錄界面的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
Python實(shí)現(xiàn)的ini文件操作類分享
這篇文章主要介紹了Python實(shí)現(xiàn)的ini文件操作類分享,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2014-11-11
Python基于回溯法子集樹模板解決野人與傳教士問(wèn)題示例
這篇文章主要介紹了Python基于回溯法子集樹模板解決野人與傳教士問(wèn)題,簡(jiǎn)單說(shuō)明了野人與傳教士問(wèn)題,并結(jié)合實(shí)例形式分析了Python使用回溯法子集樹模板解決野人與傳教士問(wèn)題的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
Linux 發(fā)郵件磁盤空間監(jiān)控(python)
這篇文章主要介紹了Linux發(fā)郵件磁盤空間監(jiān)控功能,python實(shí)現(xiàn),需要的朋友可以參考下2016-04-04

