首頁 > 軟體

Python基礎教學之例外處理詳解

2023-04-02 06:01:39

前言

最近發現有些東西長時間不用就要忘了,堅持每天覆習總結一個小知識點吧~

異常是什麼呢?就是在程式碼執行過程中非預期的執行結果,隨著程式碼越來越複雜,程式碼中的執行邏輯也會越來越複雜,如果沒有處理好異常情況,很有可能造成軟體執行錯誤,導致重大損失。相反,如果合理的處理異常情況,則可以增強軟體的穩定性,提高體驗感。

異常

Python中,使用異常物件(exception object)來表示程式碼執行過程中所發生的異常情況,當執行程式爆出錯誤的時候則會丟擲異常。

如果沒有正確處理異常,則會終止執行。

你可以想象一下,如果你在開發一款產品時,出現異常而不報告出發生異常的原因,是不是會很難受,也很難解決異常的問題。

為了提高產品的穩定性與靈活性,Python執行開發者捕捉並處理各類異常,一般的內部模組報錯如KeyError異常類較為常見,當然也有很多其他的。

錯誤與異常

簡單瞭解下,Python將程式碼執行錯誤分為兩類:語法錯誤(syntax error)和異常(exception)

語法錯誤

首先,是語法錯誤的問題。字面可知,程式碼解析錯誤。

這種錯誤通常出現在初學者,主要原因是所執行的程式碼不符合Python語法的規範,故會報出語法錯誤導致code停機。

下面給出一個錯誤示範:

>>> if for not in list(1,2,3,4)
  File "<stdin>", line 1
    if for not in list(1,2,3,4)
       ^
SyntaxError: invalid syntax

從上面的報錯中可以知道是語法錯誤,無效的語法。並且指出了錯誤的地方在for的位置,很顯然iffor不能用在一起。

異常

異常則是在程式碼執行過程中發現的錯誤,這是很難提前被發現的,即使程式碼寫的很規範標準,但也可能會出現執行異常的情況。

下面給出一個錯誤範例。經常被提到的是除數為0的情況,數學運算中,0是不可以作為除數的,如果作為除數則會爆出異常。

>>> a = 5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

很明顯報錯指出0作為除數是不對的。

例外處理

當我們瞭解了錯誤和異常後,就得處理異常情況。對於語法錯誤這種問題多多練習即可避免,對於第二種異常,python給出了try-except語句來處理。

為了更清晰的解釋,還是以上面的除數為0的情況作為例子,我們通過新增try-except語句捕捉並處理異常情況:

def division(x, y):
	try:
		return x / y
	except ZeroDivisionError:
		print("0不能作為除數!!!")

然後我們再在terminal呼叫函數試試:

division(x=1, y=0)

輸出:

0不能作為除數!!!

雖然我們的輸入是錯誤的理論應該報錯,但是並沒有報錯而且還返回了一段話。

下面解釋一下try-except語句的工作原理:

  1. Try-except中的程式碼會被正常執行
  2. 如果沒有出現異常則跳過except程式碼塊並結束try-except
  3. 如果try-except中的某一句程式碼出現了問題異常,剩餘程式碼停止執行,如果出現的異常與except所指定的一致,則執行except中的程式碼塊,例外處理結束整個應用程式繼續執行
  4. 如果出現的異常與except中指定的不符合,那麼則跳出try語句,程式繼續丟擲異常並終止執行程式碼

當然,我們寫的程式碼可能不止出現一種異常情況,我們可以將所有異常寫在一個except語句中,如下所示:

except (RuntimeError, TypeError, NameError):pass

如果捕捉到異常列表中的任意一項異常表示式,則都會進入except處理。

當然,如果你想對每一種異常進行單獨處理也可以一個一個的分開進行處理:

def passpass(x=1):
	try:
		return print(x+x)
	except (RuntimeError, TypeError, NameError):
		pass
	except TypeError:
		print('引數錯誤啦~')
	except NameError:
		print('名稱錯誤啦~')

今天先到這裡明兒再更,去跳繩了,哎,每天卷卷卷,老北京雞內卷啊~(2022.4.20)

Python的異常型別是可以繼承的, 我們在此僅需知道,若except後指定的異常繼承自前面異常,由此後面的異常也會被捕捉到,範例如下:

class A(Exception):
	pass
class B(A):
	pass
class C(B):
	pass

for cls in [A, B, C]:
	try:
		raise cls()
	except C:
		print('C')
	except B:
		print('B')
	except A:
		print('A')

則會輸出:

A
B
C

相反,如果把except的順序倒過來,則只會輸出A,由於異常B和C都繼承來自A,由此在捕捉到B異常後則會終止:

class A(Exception):
	pass
class B(A):
	pass
class C(B):
	pass

for cls in [A, B, C]:
	try:
		raise cls()
	except A:
		print('A')
	except B:
		print('B')
	except C:
		print('C')

輸出全為A:

A
A
A

如果所有異常都一一的提取出來,這會很麻煩,此時可以在最後的一個except中不設定異常型別,由此剩下沒有被捕獲的異常全會被捕捉:

def passpass(x=1):
	try:
		return print(x/x)

	except TypeError:
		print('引數錯誤啦~')
	except NameError:
		print('名稱錯誤啦~')
	except:
		print('報錯啦~自己查')

一個重要功能:else.

else語句則是用來執行一些額外操作,如try程式碼塊中執行了一些檔案操作,在else中可以釋放資源,else的語法格式如下:

try:
	pass
except:
	pass
else:
	pass

當然我們還可以操作異常,如下:

def passpass(x=1):
	try:
		return print(x/x)

	except TypeError as error:
		print('引數錯誤啦~', error)
	except NameError:
		print('名稱錯誤啦~')
	except:
		print('報錯啦~自己查')

自主丟擲異常

開發者在平常的有些情況下並沒有執行錯誤,但是不符合設計邏輯,由此需要開發者主動丟擲異常,這時我們需要使用raise語句丟擲異常:

>>> raise NameError('HiThere')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: HiThere

自定義異常

Python內建異常無法滿足開發需求的時候,可以自定義異常。

自定義異常類必須要直接或間接繼承自Exception類。自定義異常類可以像其他類一樣做任何事情,但原則上要保持簡潔,提高一些屬性即可。

class Error(Exception):
	"""Base class for exception in this module."""
	pass

class InputError(Error):
	"""Exception raised for errors in the input.

	Attributes:
		expression -- input expression in which the error occurred
		message -- explanation of the winerror

	"""
	def __init__(self, expression, message):
		self.expression = expression
		self.message = message

finally子句

else在程式碼正常執行後才會被執行的程式碼塊,但有些情況無論程式碼塊是否出現異常都要執行,則需要用到finally語句:

def passpass(x=1):
	try:
		return print(x/x)

	except TypeError as error:
		print('引數錯誤啦~', error)
	except NameError:
		print('名稱錯誤啦~')
	except:
		print('報錯啦~自己查')
	finally:
		print('運算結束~')

總結

到此這篇關於Python基礎教學之例外處理的文章就介紹到這了,更多相關Python例外處理內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com