Python中的異常處理raise案例介紹
0. 介紹
問題1: 是否可以在程序的指定位置手動拋出一個異常?
答案是肯定的,Python 允許我們在程序中手動設(shè)置異常,使用 raise 語句即可。
問題2: 我們從來都是想方設(shè)法地讓程序正常運行,為什么還要手動設(shè)置異常呢?
首先要分清楚程序發(fā)生異常和程序執(zhí)行錯誤,它們完全是兩碼事,程序由于錯誤導(dǎo)致的運行異常,是需要程序員想辦法解決的;但還有一些異常,是程序正常運行的結(jié)果,比如用 raise 手動引發(fā)的異常(比如1÷0沒有意義,程序沒有寫錯,但是這樣運算不合理,就是異常)。
raise 語句的基本語法格式為:
raise [exceptionName [(reason)]]
其中,用 [] 括起來的為可選參數(shù),其作用是指定拋出的異常名稱,以及異常信息的相關(guān)描述。
如果可選參數(shù)全部省略,則 raise 會把當(dāng)前錯誤原樣拋出;如果僅省略 (reason),則在拋出異常時,將不附帶任何的異常描述信息。
也就是說,raise 語句有如下三種常用的用法:
- raise:單獨一個 raise。該語句引發(fā)當(dāng)前上下文中捕獲的異常(比如在 except 塊中),或默認引發(fā) RuntimeError 異常。
- raise 異常類名稱:raise 后帶一個異常類名稱,表示引發(fā)執(zhí)行類型的異常。
- raise 異常類名稱(描述信息):在引發(fā)指定類型的異常的同時,附帶異常的描述信息。
代碼測試
>>> raise
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
raise
RuntimeError: No active exception to reraise>>> raise ZeroDivisionError
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise ZeroDivisionError
ZeroDivisionError
>>> raise ZeroDivisionError("除數(shù)不能為零")
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
raise ZeroDivisionError("除數(shù)不能為零")
ZeroDivisionError: 除數(shù)不能為零
1. raise 介紹(案例)
程序正常運行的時候,根據(jù)需要,用 raise 手動引發(fā)異常。
raise 語句引發(fā)的異常,通常用 try except(else finally)異常處理結(jié)構(gòu)來捕獲并進行處理。例如:
try:
a = input("輸入一個數(shù):")
#判斷用戶輸入的是否為數(shù)字
if(not a.isdigit()):
raise ValueError("a 必須是數(shù)字")
except ValueError as e:
print("引發(fā)異常:", repr(e))
當(dāng)我們輸入字母 a ,程序運行結(jié)果為:
runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
輸入一個數(shù):>? a
引發(fā)異常: ValueError('a 必須是數(shù)字')
當(dāng)我們輸入數(shù)字 8,程序運行結(jié)果為:
輸入一個數(shù):8
由上面示例可以看出,我們手動讓程序引發(fā)異常,很多時候并不是為了讓其崩潰。
2. raise 不需要參數(shù)(案例)
這里重點關(guān)注位于 except 塊中的 raise
try:
a = input("輸入一個數(shù):")
if(not a.isdigit()):
raise ValueError("a 必須是數(shù)字")
except ValueError as e:
print("引發(fā)異常:", repr(e))
raise
由于在其之前我們已經(jīng)手動引發(fā)了 ValueError 異常,因此這里當(dāng)再使用 raise 語句時,它會再次引發(fā)一次。當(dāng)我們輸入字母 a ,程序執(zhí)行結(jié)果為:
In[2]: runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
輸入一個數(shù):a
引發(fā)異常: ValueError('a 必須是數(shù)字',)
Traceback (most recent call last):
File "D:\python3.6\1.py", line 4, in <module>
raise ValueError("a 必須是數(shù)字")
ValueError: a 必須是數(shù)字這里重點關(guān)注位于 except 塊中的 raise,由于在其之前我們已經(jīng)手動引發(fā)了 ValueError 異常,因此這里當(dāng)再使用 raise 語句時,它會再次引發(fā)一次。
3. raise:單獨一個 raise(正常程序使用無參的 raise )
當(dāng)在沒有引發(fā)過異常的程序使用無參的 raise 語句時,它默認引發(fā)的是 RuntimeError 異常。例如:
try:
a = input("輸入一個數(shù):")
if(not a.isdigit()):
raise
except RuntimeError as e:
print("引發(fā)異常:", repr(e))當(dāng)我們輸入字母 a ,程序執(zhí)行結(jié)果為:
In[3]: runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
輸入一個數(shù):>? a
引發(fā)異常: RuntimeError('No active exception to reraise')
4. 其它案例
4.1 案例1
def read_file(file, pattern):
try:
if file.endswith('rtd'):
data = pd.read_csv(file, skiprows=41, sep=r'\t')
elif file.endswith('csv'):
data = pd.read_csv(file)
else:
raise ValueError("Unknown file type")
data = extract_cols(data, pattern=pattern, file=file)
except Exception as e:
print(f"{os.path.basename(file).split('.')[0]}: {e}")
data = pd.DataFrame()
return data
4.2 案例2
def divide(a, b):
return a/b
try:
divide(1, 0)
except:
print("divide by 0")
else:
print("the code is no problem")
print("code after try catch,hello,world!")輸出結(jié)果
divide by 0
code after try catch,hello,world!
5. 處理流程
try: code #需要判斷是否會拋出異常的代碼,如果沒有異常處理,python會直接停止執(zhí)行程序 except: #這里會捕捉到上面代碼中的異常,并根據(jù)異常拋出異常處理信息 #except ExceptionName,args: #同時也可以接受異常名稱和參數(shù),針對不同形式的異常做處理 code #這里執(zhí)行異常處理的相關(guān)代碼,打印輸出等 else: #如果沒有異常則執(zhí)行else code #try部分被正常執(zhí)行后執(zhí)行的代碼 finally: code #退出try語句塊總會執(zhí)行的程序
可以看到,
- 這里的 else 是和 try-catch 連用的,并且 else 只在 try 中代碼沒有異常的情況下執(zhí)行,else 必須在 except 這句代碼存在的時候才能出現(xiàn)。
- finally 這個片段里面的代碼是肯定在最后執(zhí)行的,無論前面是否發(fā)生異常,最后總會執(zhí)行finally片段內(nèi)的代碼。
- 所以,正常的流程是:try 沒有發(fā)生錯誤-》else 內(nèi)的代碼-》finally 中的代碼。
- 發(fā)生異常的流程是:try 中發(fā)生異常-》被 except 捕獲并執(zhí)行 except 片段中的代碼-》執(zhí)行 finally 中的代碼。
6. 顯示error位置
要在拋出異常時包含代碼所在的位置,可以使用Python的traceback模塊。這個模塊可以獲取異常發(fā)生時的堆棧信息,包括文件名和行號。
以下是一個示例代碼,展示了如何在捕獲異常時打印出詳細的錯誤信息,包括代碼所在的位置:
import traceback
try:
# 假設(shè)這是可能會拋出異常的代碼
# 例如:result = 10 / 0 # 這將引發(fā)ZeroDivisionError
result = 10 / 0
except Exception as e:
# 獲取異常信息和堆棧跟蹤
tb = traceback.format_exc()
print(f"Error processing {filename}: {e}\nTraceback:\n{tb}")在這個示例中,traceback.format_exc()會返回一個字符串,其中包含了異常的詳細信息和堆棧跟蹤,包括引發(fā)異常的文件名和行號。這樣,就可以清楚地看到錯誤發(fā)生的位置。??
錯誤信息如下:
Error processing : division by zero
Traceback:
Traceback (most recent call last):
File "<ipython-input-5-6bef8f98af92>", line 6, in <module>
result = 10 / 0
ZeroDivisionError: division by zero
總結(jié)
也就是說,raise 語句有如下三種常用的用法:
1.raise:單獨一個 raise。該語句引發(fā)當(dāng)前上下文中捕獲的異常(比如在 except 塊中),或默認引發(fā) RuntimeError 異常。
2.raise 異常類名稱:raise 后帶一個異常類名稱,表示引發(fā)執(zhí)行類型的異常。
3.raise 異常類名稱(描述信息):在引發(fā)指定類型的異常的同時,附帶異常的描述信息。
參考鏈接:
鏈接1、
到此這篇關(guān)于Python中的異常處理raise案例介紹的文章就介紹到這了,更多相關(guān)python 異常處理raise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Pycharm配置翻譯插件Translation報錯更新TTK失敗不能使用的問題
這篇文章主要介紹了關(guān)于Pycharm配置翻譯插件Translation報錯更新TTK失敗不能使用的問題,本文通過圖文并茂的形式給大家分享解決方案,需要的朋友可以參考下2022-04-04
深入理解Python中的 __new__ 和 __init__及區(qū)別介紹
這篇文章主要介紹了深入理解Python中的 __new__ 和 __init__及區(qū)別介紹,這兩個方法的主要區(qū)別在于:__new__ 負責(zé)對象的創(chuàng)建而 __init__ 負責(zé)對象的初始化。具體內(nèi)容詳情大家跟隨小編一起看看吧2018-09-09
把JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對象方法詳解(兩種方法)
本文通過兩種方法給大家介紹了把JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對象,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-06-06

