Python中?try?/?except?/?else?/?finally?異常處理方法詳解
1. 基本結(jié)構(gòu)
try:
# 可能會(huì)拋出異常的代碼
except SomeException as e:
# 捕獲并處理異常
else:
# 如果 try 中代碼沒(méi)有異常,就執(zhí)行這里
finally:
# 無(wú)論是否發(fā)生異常,最后都會(huì)執(zhí)行這里
2. 各部分的作用
try
- 用途:包含可能發(fā)生異常的代碼段。
- 如果代碼沒(méi)有異常,則
except不會(huì)被執(zhí)行,直接進(jìn)入else(如果有的話)。 - 如果有異常,則轉(zhuǎn)到對(duì)應(yīng)的
except。
except
- 用途:捕獲并處理異常。
- 可以寫(xiě)多個(gè)
except,匹配不同的異常類(lèi)型。
示例:
try:
x = int("abc") # 會(huì)觸發(fā) ValueError
except ValueError:
print("捕獲到 ValueError")
except TypeError:
print("捕獲到 TypeError")
else
- 用途:只有當(dāng) try 中沒(méi)有發(fā)生任何異常時(shí) 才會(huì)執(zhí)行。
- 常用于把 不需要異常保護(hù)的邏輯 放在這里,讓
try中的代碼盡量簡(jiǎn)潔。
示例:
try:
result = 10 / 2
except ZeroDivisionError:
print("除零錯(cuò)誤")
else:
print("計(jì)算成功,結(jié)果是:", result)
運(yùn)行結(jié)果:
計(jì)算成功,結(jié)果是: 5.0
finally
- 用途:無(wú)論是否發(fā)生異常,都會(huì)執(zhí)行。
- 常用于資源釋放、文件關(guān)閉、鎖釋放等。
示例:
try:
f = open("test.txt", "r")
data = f.read()
except FileNotFoundError:
print("文件不存在")
else:
print("讀取成功")
finally:
print("執(zhí)行 finally")
if 'f' in locals() and not f.closed:
f.close()
3. 執(zhí)行流程總結(jié)
| 情況 | try | except | else | finally |
|---|---|---|---|---|
| 沒(méi)有異常 | 執(zhí)行 | 跳過(guò) | 執(zhí)行 | 執(zhí)行 |
| 有異常,匹配到 | 執(zhí)行到異常處中斷 | 執(zhí)行 | 跳過(guò) | 執(zhí)行 |
| 有異常,未匹配到 | 執(zhí)行到異常處中斷 | 不執(zhí)行 | 不執(zhí)行 | 執(zhí)行(然后異常繼續(xù)向上拋出) |
4. 常見(jiàn)用法
(1)多個(gè)except
try:
x = int("abc")
except ValueError:
print("數(shù)值錯(cuò)誤")
except Exception as e:
print("其他異常:", e)
(2)捕獲多個(gè)異常
try:
x = int("abc")
except (ValueError, TypeError) as e:
print("捕獲到異常:", e)
(3)用else處理后續(xù)邏輯
try:
num = int("123")
except ValueError:
print("轉(zhuǎn)換失敗")
else:
print("轉(zhuǎn)換成功,結(jié)果是:", num)
(4)finally釋放資源
try:
f = open("data.txt", "r")
data = f.read()
except FileNotFoundError:
print("文件沒(méi)找到")
finally:
print("關(guān)閉文件")
if 'f' in locals() and not f.closed:
f.close()
5. 容易踩的坑
- finally 中的 return 會(huì)覆蓋異常
def foo():
try:
return 1
finally:
return 2
print(foo()) # 輸出 2,而不是 1
說(shuō)明:finally 里的 return、break、continue 都會(huì)覆蓋 try/except/else 的返回值或異常。
過(guò)度使用 try
- 最佳實(shí)踐:只把 可能發(fā)生異常的最小代碼塊 放進(jìn)
try,不要把一大段邏輯全包進(jìn)去。
- 最佳實(shí)踐:只把 可能發(fā)生異常的最小代碼塊 放進(jìn)
6.常用場(chǎng)景示例
下面 6 個(gè)示例覆蓋了:
- 文件操作
- 用戶(hù)輸入
- 網(wǎng)絡(luò)請(qǐng)求
- 多異常捕獲
- 數(shù)據(jù)庫(kù)操作
- 臨時(shí)文件清理
示例 1:文件讀取(帶finally關(guān)閉資源)
try:
f = open("test.txt", "r")
data = f.read()
except FileNotFoundError:
print("文件不存在")
else:
print("文件內(nèi)容:", data)
finally:
if 'f' in locals() and not f.closed:
f.close()
print("文件已關(guān)閉")
應(yīng)用場(chǎng)景:文件操作時(shí),確保資源一定會(huì)被關(guān)閉。
示例 2:用戶(hù)輸入校驗(yàn)
try:
num = int(input("請(qǐng)輸入一個(gè)整數(shù): "))
except ValueError:
print("輸入無(wú)效,請(qǐng)輸入整數(shù)!")
else:
print("你輸入的整數(shù)是:", num)
應(yīng)用場(chǎng)景:處理用戶(hù)輸入時(shí)防止格式錯(cuò)誤。
示例 3:網(wǎng)絡(luò)請(qǐng)求(簡(jiǎn)化版)
import requests
try:
response = requests.get("https://httpbin.org/get")
data = response.json()
except requests.RequestException as e:
print("請(qǐng)求失敗:", e)
else:
print("請(qǐng)求成功,返回?cái)?shù)據(jù):", data)
finally:
print("請(qǐng)求結(jié)束")
應(yīng)用場(chǎng)景:網(wǎng)絡(luò)請(qǐng)求一定要有異常處理,否則一旦超時(shí)或斷網(wǎng)就會(huì)崩潰。
示例 4:多個(gè)異常捕獲
try:
x = int("abc") # ValueError
y = 10 / 0 # ZeroDivisionError
except ValueError:
print("數(shù)值轉(zhuǎn)換錯(cuò)誤")
except ZeroDivisionError:
print("除零錯(cuò)誤")
except Exception as e:
print("其他錯(cuò)誤:", e)
應(yīng)用場(chǎng)景:針對(duì)不同錯(cuò)誤分類(lèi)處理,更清晰。
示例 5:數(shù)據(jù)庫(kù)操作(帶finally釋放連接)
class FakeDB:
def connect(self): print("連接數(shù)據(jù)庫(kù)")
def close(self): print("關(guān)閉數(shù)據(jù)庫(kù)")
def query(self): return [1, 2, 3]
db = FakeDB()
try:
db.connect()
result = db.query()
except Exception as e:
print("查詢(xún)失敗:", e)
else:
print("查詢(xún)結(jié)果:", result)
finally:
db.close()
應(yīng)用場(chǎng)景:數(shù)據(jù)庫(kù)、消息隊(duì)列、Socket等操作中保證資源一定釋放。
示例 6:finally保證清理臨時(shí)文件
import os
try:
with open("temp.txt", "w") as f:
f.write("臨時(shí)數(shù)據(jù)")
raise RuntimeError("模擬出錯(cuò)")
except RuntimeError as e:
print("捕獲到異常:", e)
finally:
if os.path.exists("temp.txt"):
os.remove("temp.txt")
print("臨時(shí)文件已刪除")
應(yīng)用場(chǎng)景:程序中斷時(shí)確保臨時(shí)文件、緩存不會(huì)遺留。
7. 總結(jié)口訣
try:放可能出錯(cuò)的代碼except:出錯(cuò)就處理else:沒(méi)出錯(cuò)才執(zhí)行finally:一定會(huì)執(zhí)行
高級(jí)應(yīng)用內(nèi)容
高級(jí)應(yīng)用主要涉及:
- 異常鏈:處理后再拋出
- 自定義異常:模塊化項(xiàng)目常用
- 上下文管理器:優(yōu)雅封裝
try/finally - 邏輯分層:
else只放成功邏輯 - finally 覆蓋陷阱:調(diào)試必知
- contextlib.suppress:優(yōu)雅忽略異常
- 事務(wù)回滾:數(shù)據(jù)庫(kù)/分布式系統(tǒng)
- 多線程異常處理:防止異常丟失
下面分別舉例說(shuō)明,具體內(nèi)容如下:
1. 捕獲并重新拋出異常(異常鏈)
有時(shí)需要先處理一下,再把異常繼續(xù)拋給上層:
def process_data(data):
try:
return int(data)
except ValueError as e:
print("日志記錄:數(shù)據(jù)轉(zhuǎn)換失敗 ->", e)
raise # 重新拋出異常,讓上層調(diào)用者知道
應(yīng)用場(chǎng)景:日志記錄、錯(cuò)誤追蹤。
2. 自定義異常類(lèi)
在工程里,為了更清晰區(qū)分錯(cuò)誤類(lèi)型,常會(huì)定義自家異常:
class DataFormatError(Exception):
pass
def load_data(data):
if not isinstance(data, dict):
raise DataFormatError("數(shù)據(jù)必須是字典類(lèi)型")
try:
load_data("not_dict")
except DataFormatError as e:
print("捕獲到自定義異常:", e)
應(yīng)用場(chǎng)景:大型項(xiàng)目中,給模塊定義專(zhuān)屬錯(cuò)誤類(lèi)型,便于精確捕獲。
3.with上下文管理器的異常處理
上下文管理器的 __exit__ 方法可以接收異常,并決定是否吞掉:
class Demo:
def __enter__(self):
print("進(jìn)入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
if exc_type:
print("捕獲異常:", exc_type, exc_val)
return True # 返回 True 表示異常已處理,不會(huì)再拋出
with Demo():
print("運(yùn)行中...")
raise ValueError("測(cè)試異常")
print("程序繼續(xù)執(zhí)行")
應(yīng)用場(chǎng)景:數(shù)據(jù)庫(kù)事務(wù)、文件操作、鎖等,結(jié)合 try/finally 自動(dòng)化資源管理。
4.try/except/else結(jié)合邏輯分層
讓 try 只負(fù)責(zé)可能出錯(cuò)的部分,后續(xù)邏輯放到 else,保持結(jié)構(gòu)清晰:
try:
f = open("config.json")
config = f.read()
except FileNotFoundError:
print("配置文件缺失")
else:
print("配置文件加載成功")
finally:
if 'f' in locals():
f.close()
應(yīng)用場(chǎng)景:避免把無(wú)關(guān)代碼放進(jìn) try,提高可讀性。
5.finally中的清理 vs. 異常屏蔽
注意:如果 finally 里有 return/raise,會(huì)覆蓋原異常:
def test():
try:
1 / 0
except ZeroDivisionError:
print("捕獲到異常")
raise
finally:
return "finally 覆蓋了異常"
print(test()) # 輸出 "finally 覆蓋了異常"
應(yīng)用場(chǎng)景:調(diào)試時(shí)要小心,避免無(wú)意中吞掉異常。
6.contextlib.suppress—— 優(yōu)雅忽略異常
Python 內(nèi)置的工具類(lèi),可以用來(lái)代替 try/except/pass:
import contextlib
with contextlib.suppress(FileNotFoundError):
with open("no_such_file.txt") as f:
data = f.read()
print("即使文件不存在,程序也能繼續(xù)運(yùn)行")
應(yīng)用場(chǎng)景:當(dāng)你明確不關(guān)心某些異常時(shí),代碼更簡(jiǎn)潔。
7. 異常和事務(wù)(數(shù)據(jù)庫(kù)/分布式)
很多數(shù)據(jù)庫(kù)驅(qū)動(dòng)會(huì)在 try/except/finally 中實(shí)現(xiàn)事務(wù)控制:
try:
db.begin()
db.insert("users", {"id": 1, "name": "Alice"})
db.commit()
except Exception as e:
db.rollback()
print("事務(wù)失敗:", e)
應(yīng)用場(chǎng)景:保證數(shù)據(jù)一致性。
8. 異常與多線程
在多線程中,子線程的異常不會(huì)自動(dòng)傳遞到主線程,需要顯式捕獲:
import threading
def worker():
try:
1 / 0
except Exception as e:
print("子線程異常:", e)
t = threading.Thread(target=worker)
t.start()
t.join()
應(yīng)用場(chǎng)景:多線程/異步編程中異常管理。
總結(jié)
到此這篇關(guān)于Python中try/except/else/finally異常處理方法詳解的文章就介紹到這了,更多相關(guān)Python try/except/else/finally異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- python try except 捕獲所有異常的實(shí)例
- Python使用try except處理程序異常的三種常用方法分析
- Python異常處理:try、except、else、finally的全面解析
- 對(duì)python中的try、except、finally 執(zhí)行順序詳解
- Python中的異常處理try/except/finally/raise用法分析
- python try except返回異常的信息字符串代碼實(shí)例
- python嵌套try...except如何使用詳解
- Python try except else使用詳解
- python中try Except拋出異常的使用方式
相關(guān)文章
python中enumerate函數(shù)遍歷元素用法分析
這篇文章主要介紹了python中enumerate函數(shù)遍歷元素用法,結(jié)合實(shí)例形式分析了enumerate函數(shù)遍歷元素的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-03-03
Python實(shí)現(xiàn)圖的廣度和深度優(yōu)先路徑搜索算法
圖是一種抽象數(shù)據(jù)結(jié)構(gòu),本質(zhì)和樹(shù)結(jié)構(gòu)是一樣的。圖與樹(shù)相比較,圖具有封閉性,可以把樹(shù)結(jié)構(gòu)看成是圖結(jié)構(gòu)的前生。本文將利用Python實(shí)現(xiàn)圖的廣度和深度優(yōu)先路徑搜索算法,感興趣的可以學(xué)習(xí)一下2022-04-04
pytest解讀fixtures中yield與addfinalizer區(qū)別
這篇文章主要為大家介紹了pytest官方解讀fixtures中yield與addfinalizer區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
python函數(shù)調(diào)用,循環(huán),列表復(fù)制實(shí)例
這篇文章主要介紹了python函數(shù)調(diào)用,循環(huán),列表復(fù)制實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
Python基于PycURL自動(dòng)處理cookie的方法
這篇文章主要介紹了Python基于PycURL自動(dòng)處理cookie的方法,實(shí)例分析了Python基于curl操作cookie的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
Python結(jié)合OpenCV實(shí)現(xiàn)簡(jiǎn)單的圖像拼接功能
這篇文章主要為大家詳細(xì)介紹了Python如何使用OpenCV實(shí)現(xiàn)簡(jiǎn)單圖像拼接的核心概念與技術(shù)要點(diǎn),主要內(nèi)容包括圖像獲取,處理,特征提取等關(guān)鍵環(huán)節(jié),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-05-05
python人工智能算法之差分進(jìn)化算法的實(shí)現(xiàn)
DE基于GA,正如進(jìn)化基于遺傳,和遺傳算法相比,差分進(jìn)化引入了差分變異模式,相當(dāng)于開(kāi)辟了一條嶄新的進(jìn)化路徑,下面就來(lái)看看差分優(yōu)化算法是如何實(shí)現(xiàn)的吧2023-08-08

