Python異常處理
Python提供了兩個非常重要的功能來處理Python程序中的異常和錯誤,並在其中添加調試的函數功能 -
- 異常處理 - 在本教程中介紹。這是一個列表標準Python中提供的異常 - 標準異常。
- 斷言 - 在Python 3教程中的斷言中介紹。
標準異常
以下是Python中可用的標準異常列表 -
編號
異常名稱
描述
1
Exception
所有異常的基類
2
StopIteration
當迭代器的next()
方法沒有指向任何對象時引發。
3
SystemExit
由sys.exit()
函數引發。
4
StandardError
除StopIteration
和SystemExit
之外的所有內置異常的基類。
5
ArithmeticError
數據計算出現的所有錯誤的基類。
6
OverflowError
當計算超過數字類型的最大限制時引發。
7
FloatingPointError
當浮點計算失敗時觸發。
8
ZeroDivisonError
對於所有的數字類型,當對零進行除數或模數時產生。
9
AssertionError
在Assert
語句失敗的情況下引發。
10
AttributeError
在屬性引用或分配失敗的情況下引發。
11
EOFError
當沒有來自raw_input()
或input()
函數的輸入並且達到文件結尾時引發。
12
ImportError
導入語句失敗時引發。
13
KeyboardInterrupt
當用戶中斷程序執行時,通常按Ctrl + c
。
14
LookupError
所有查找錯誤的基類。
15
IndexError
當序列中沒有找到索引時引發。
16
KeyError
當在字典中找不到指定的鍵時引發。
17
NameError
當在本地或全局命名空間中找不到標識符時引發。
18
UnboundLocalError
當嘗試訪問函數或方法中的局部變量但未分配值時引發。
19
EnvironmentError
在Python環境之外發生的所有異常的基類。
20
IOError
在嘗試打開不存在的文件時,輸入/輸出操作失敗時觸發,例如print
語句或open()
函數。
21
OSError
引起操作系統相關的錯誤。
22
SyntaxError
當Python語法有錯誤時引發。
23
IndentationError
當縮進未正確指定時觸發。
24
SystemError
當解釋器發現內部問題時引發,但遇到此錯誤時,Python解釋器不會退出。
25
SystemExit
當Python解釋器通過使用sys.exit()
函數退出時引發。 如果沒有在代碼中處理,導致解釋器退出。
26
TypeError
在嘗試對指定數據類型無效的操作或函數時引發。
27
ValueError
當數據類型的內置函數具有有效參數類型時引發,但參數具有指定的無效值。
28
RuntimeError
產生的錯誤不屬於任何類別時引發。
29
NotImplementedError
當需要在繼承類中實現的抽象方法實際上沒有實現時引發。
Python中的斷言
斷言是一個健全檢查,可以在完成對程序的測試後打開或關閉。
試想斷言的最簡單的方法就是將它與一個
raise-if
語句(或者更準確的說是一個加註if
語句)相對應。測試表達式,如果結果爲false
,則會引發異常。斷言由版本
1.5
引入的assert
語句來執行,它是Python的最新關鍵字。程序員經常在函數開始時放置斷言來檢查有效的輸入,並在函數調用後檢查有效的輸出。
assert語句
當它遇到一個assert
語句時,Python會評估求值它的的表達式,是否爲所希望的那樣。 如果表達式爲false
,Python會引發AssertionError
異常。
assert
的語法是 -
assert Expression[, Arguments]
如果斷言失敗,Python將使用ArgumentExpression
作爲AssertionError
的參數。 使用try-except
語句可以像任何其他異常一樣捕獲和處理AssertionError
異常。 如果沒有處理,它們將終止程序併產生回溯。
**
示例**
這裏將實現一個功能:將給定的溫度從開爾文轉換爲華氏度。如果是負溫度,該功能將退出 -
#!/usr/bin/python3
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print (KelvinToFahrenheit(273))
print (int(KelvinToFahrenheit(505.78)))
print (KelvinToFahrenheit(-5))
當執行上述代碼時,會產生以下結果 -
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
什麼是異常?
一個例外是在程序執行期間發生的一個事件,它破壞程序指令的正常流程。 一般來說,當Python腳本遇到無法應對的情況時,會引發異常。異常是一個表示錯誤的Python對象。
當Python腳本引發異常時,它必須立即處理異常,否則終止並退出。
處理異常
如果有一些可能引發異常的可疑代碼,可以通過將可疑代碼放在try:
塊中來保護您的程序。 在try:
塊之後,包括一個except:
語句,然後是一個儘可能優雅地處理問題的代碼塊。
語法
下面是簡單的語法try .... except ... else
塊 -
try:
You do your operations here
......................
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......................
else:
If there is no exception then execute this block.
以下是上述語法的幾個重點 -
- 一個
try
語句可以有多個except
語句。 當try
塊包含可能引發不同類型的異常的語句時,這就很有用。 - 還可以提供一個通用的
except
子句,它處理任何異常。 - 在
except
子句之後,可以包含一個else
子句。 如果try:block
中的代碼不引發異常,則else
塊中的代碼將執行。 -
else-block
是一個不需要try:block
保護的代碼的地方。
示例
此示例打開一個文件,將內容寫入文件,並且優雅地出現,因爲完全沒有問題 -
#!/usr/bin/python3
try:
fh = open("testfile", "w")
fh.write("This is my test file for exception handling!!")
except IOError:
print ("Error: can\'t find file or read data")
else:
print ("Written content in the file successfully")
fh.close()
這產生以下結果 -
Written content in the file successfully
示例
此示例嘗試打開一個沒有寫入權限的文件,因此它引發了一個異常 -
#!/usr/bin/python3
try:
fh = open("testfile", "r")
fh.write("This is my test file for exception handling!!")
except IOError:
print ("Error: can\'t find file or read data")
else:
print ("Written content in the file successfully")
這產生以下結果 -
Error: can't find file or read data
except子句沒有指定異常
也可以使用except
語句,但不定義異常,如下所示 -
try:
You do your operations here
......................
except:
If there is any exception, then execute this block.
......................
else:
If there is no exception then execute this block.
這種try-except
語句捕獲所有發生的異常。使用這種try-except
語句不被認爲是一個很好的編程實踐,因爲它捕獲所有異常,但不會讓程序員能更好地識別發生的問題的根本原因。
except子句指定多個異常
還可以使用相同的except
語句來處理多個異常,如下所示:
try:
You do your operations here
......................
except(Exception1[, Exception2[,...ExceptionN]]]):
If there is any exception from the given exception list,
then execute this block.
......................
else:
If there is no exception then execute this block.
try-finally子句
可以使用finally:
塊和try:
塊。 finally:
塊是放置必須執行代碼的地方,無論try
塊是否引發異常。 try-finally
語句的語法是這樣的 -
try:
You do your operations here;
......................
Due to any exception, this may be skipped.
finally:
This would always be executed.
......................
注意 - 可以提供
except
子句或finally
子句,但不能同時提供。不能使用else
子句以及finally
子句。
示例
#!/usr/bin/python3
try:
fh = open("testfile", "w")
fh.write("This is my test file for exception handling!!")
finally:
print ("Error: can\'t find file or read data")
fh.close()
如果沒有以寫入形式打開文件的權限,則會產生以下結果 -
Error: can't find file or read data
同樣的例子可以寫得更乾淨如下 -
#!/usr/bin/python3
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
print ("Going to close the file")
fh.close()
except IOError:
print ("Error: can\'t find file or read data")
當try
塊中拋出異常時,執行將立即傳遞給finally
塊。 在finally
塊中的所有語句都被執行之後,異常被再次引發,如果存在於try-except
語句的下一個更高的層中,則在except
語句中處理異常。
異常參數
一個異常可以有一個參數,參數它是一個值,它提供有關該問題的其他信息。 參數的內容因異常而異。 可以通過在except
子句中提供變量來捕獲異常的參數,如下所示:
try:
You do your operations here
......................
except ExceptionType as Argument:
You can print value of Argument here...
如果編寫代碼來處理單個異常,則可以在except
語句中使用一個變量後跟異常的名稱。 如果要捕獲多個異常,可以使用一個變量後跟隨異常的元組。
此變量接收大部分包含異常原因的異常值。 變量可以以元組的形式接收單個值或多個值。 該元組通常包含錯誤字符串,錯誤編號和錯誤位置。
示例
以下是一個例外 -
#!/usr/bin/python3
# Define a function here.
def temp_convert(var):
try:
return int(var)
except ValueError as Argument:
print ("The argument does not contain numbers\n", Argument)
# Call above function here.
temp_convert("xyz")
這產生以下結果 -
The argument does not contain numbers
invalid literal for int() with base 10: 'xyz'
拋出異常
可以通過使用raise
語句以多種方式引發異常。raise
語句的一般語法如下 -
語法
raise [Exception [, args [, traceback]]]
這裏,Exception
是異常的類型(例如,NameError
),args
是異常參數的值。 參數是可選的; 如果沒有提供,則異常參數爲None
。
最後一個參數traceback
也是可選的(在實踐中很少使用),如果存在,則是用於異常的追溯對象。
示例
異常可以是字符串,類或對象。 Python核心引發的大多數異常都是類,一個參數是類的一個實例。 定義新的例外是非常容易的,可以做到如下 -
def functionName( level ):
if level <1:
raise Exception(level)
# The code below to this would not be executed
# if we raise the exception
return level
注意 - 爲了捕獲異常,「
except
」子句必須引用與類對象或簡單字符串相同的異常。例如,爲了捕獲上述異常,必須寫出except
子句如下:
try:
Business Logic here...
except Exception as e:
Exception handling here using e.args...
else:
Rest of the code here...
以下示例說明了使用引發異常 -
#!/usr/bin/python3
def functionName( level ):
if level <1:
raise Exception(level)
# The code below to this would not be executed
# if we raise the exception
return level
try:
l = functionName(-10)
print ("level = ",l)
except Exception as e:
print ("error in level argument",e.args[0])
這將產生以下結果 -
error in level argument -10
用戶定義的異常
Python還允許通過從標準內置異常導出類來創建自己的異常。
這是一個與RuntimeError
有關的示例。 在這裏,從RuntimeError
類創建一個子類。 當需要在捕獲異常時顯示更多具體信息時,這就很有用了。
在try
塊中,用戶定義的異常被引發並被捕獲在except
塊中。 變量e
用於創建Networkerror
類的實例。
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg
所以當定義了上面的類以後,就可以使用以下命令拋出異常 -
try:
raise Networkerror("Bad hostname")
except Networkerror,e:
print e.args