一、什么是異常(Exception)?
異常是指程序運行過程中出現的錯誤情況。比如:
- 打開一個不存在的文件
- 0作為除數
- 列表索引越界
- 類型轉換失敗
二、基本結構:try...except
try:# 可能出錯的代碼
except 錯誤類型:# 出錯時執行的代碼
示例:
try:x = 10 / 0 # 除零錯誤
except ZeroDivisionError:print("不能除以0")
輸出:
不能除以0
三、完整結構詳解
try:# 嘗試執行的代碼塊
except 錯誤類型1:# 捕獲錯誤類型1后的處理
except 錯誤類型2:# 捕獲錯誤類型2后的處理
else:# 沒有異常時執行
finally:# 無論是否有異常都執行(如關閉文件/資源)
示例:
try:num = int(input("請輸入一個整數:"))result = 10 / num
except ValueError:print("請輸入有效的整數")
except ZeroDivisionError:print("不能輸入0")
else:print("結果是:",result)
finally:print("程序結束")
四、常見異常類型及用途
異常類型 | 觸發場景 |
ZeroDivisionError | 除以零 |
ValueError | 類型轉換失敗,如 int("abc") |
IndexError | 索引超出列表范圍 |
KeyError | 字典中訪問不存在的鍵 |
FileNotFoundError | 打開一個不存在的文件 |
TypeError | 操作類型不兼容 |
五、常見實用技巧和場景
1.捕獲多個異常
try:a = int("abc")b = 10 /0
except (ValueError,ZeroDivisionError) as e:print("出錯啦",e)
2.不確定錯誤類型,先寫Exception
try:# 復雜邏輯do_something()
except Exception as e:print("出現未知錯誤",e)
注意:不要濫用Exception,否則可能掩蓋真正的bug
3.使用finally清理資源
try:file = open("data.txt","r")content = file.read()
except FileNotFound:print("文件未找到")
finally:file.close()print("文件關閉")
4.自定義函數內使用try-except
def safe_divide(x,y):try:return x/yecxept ZeroDivisionError:return "不能除以0"print(safe_divide(10,0)) #輸出:不能除以0
六、自定義異常類(Custom Exceptions)
有時候內置異常不能準確表達業務邏輯,此時可以自定義異常類
語法:
class 自定義異常名(Exception):pass
示例:
# 定義一個自定義異常類,繼承自內置的Exception類
class PasswordTooShortError(Exception):"""密碼長度太短的異常"""pass# 定義一個檢查密碼的函數
def check_password(pwd):#如果密碼長度小于6,就主動拋出自定義異常if len(pwd)<6:raise PasswordTooShortError("密碼長度不能少于6位")# 使用try-except捕獲自定義異常
try:check_password("abc")
except PasswordTooShortError as e:#捕獲到自定義異常后,打印錯誤信息print("發生錯誤:",e)
七、使用raise主動拋出異常
raise可以手動觸發異常,讓函數調用者知道出錯了
基本用法:
raise 異常類型("錯誤信息")
示例:
# 定義一個除法函數,帶參數檢查
def divide(x,y):# 如果除數是0,就主動拋出除零異常if y == 0:rasie ZeroDivisionError("除數不能為0")# 否則返回除法結果return x/y# 使用try-except 捕獲異常
try:result = divide(10,0)
except ZeroDivisionError as e: #重命名異常,以便于后續再輸出錯誤信息print("錯誤",e)
八、異常鏈(raise...from...)
在某些場景中,一個異常是由另一個異常引起的,為了因果鏈,可以使用:
raise 新異常 from 原始異常
示例:
# 定義一個讀取配置文件的函數
def read_config(path):try:# 試圖打開并讀取文件內容with open(path) as f:return f.read()except FileNotFoundError as e:# 如果文件找不到,拋出新的RuntimeError,并保留原始異常信息raise RuntimeError("配置文件讀取失敗") from e# 使用try-except捕獲RuntimeError
try:read_config("no_such_file.cfg") #嘗試讀取一個不存在的文件
except RuntimeError as e:#打印新的異常信息print("RuntimeError:",e)#打印原始異常的詳細原因(通過異常鏈追蹤)print("原始原因:",e.__casuse__)
九、高級技巧總結表
技巧 | 說明 | 示例代碼 |
自定義異常類 | 用于表達特定業務邏輯錯誤 | class MyError(Exception):.. |
raise拋出異常 | 控制程序流,校驗參數 | raise ValueError("不合法") |
raise from原始異常 | 保留原始異常上下文 | raise NewError from old_error |
異常嵌套處理 | 不同層次處理不同錯誤 | 外層用broad except,內層細分異常處理 |
異常日志記錄 | 結合logging模塊記錄錯誤信息 | logging.exception(e) |