Python3例外處理


Python提供了兩個非常重要的功能,以處理任何意外錯誤在你的Python程式,並在它們上面新增了偵錯功能 -
  • 例外處理: 這將在本教學所覆蓋講解。這是 Python 提供的標準異常的列表:標準異常

  • 斷言: 這將在 Python3斷言教學覆蓋。

標準異常如下列表 -
異常名稱
描述
Exception
所有異常的基礎類別
StopIteration
當一個疊代器的 next()方法不指向任何物件時引發
SystemExit
由 sys.exit()函式引發
StandardError
除了StopIteration異常和SystemExit,所有內建異常的基礎類別
ArithmeticError
數值計算所發生的所有錯誤的基礎類別
OverflowError
當數位型別計算超過最高限額引發
FloatingPointError
當一個浮點運算失敗時觸發
ZeroDivisonError
當除運算或模零在所有數值型別運算時引發
AssertionError
斷言語句失敗的情況下引發
AttributeError
屬性參照或賦值失敗的情況下引發
EOFError
當從 raw_input() 與 input() 函式輸入,到達檔案末尾時觸發
ImportError
當一個 import 語句失敗時觸發
KeyboardInterrupt
當使用者中斷程式執行,通常是通過按 Ctrl+c 引發
LookupError
所有查詢錯誤基礎類別

IndexError

KeyError

當在一個序列中沒有找到一個索引時引發
當指定的鍵沒有在字典中找到引發
NameError
當在區域性或全域性名稱空間中找不到的標識引發

UnboundLocalError

EnvironmentError

試圖存取在函式或方法的區域性變數時引發,但沒有值分配給它。
Python環境之外發生的所有異常的基礎類別。

IOError

IOError

當一個輸入/輸出操作失敗,如列印語句或 open()函式試圖開啟不存在的檔案時引發
作業系統相關的錯誤時引發

SyntaxError

IndentationError

當在Python語法錯誤引發;
沒有正確指定縮排引發。
SystemError
當直譯器發現一個內部問題,但遇到此錯誤時,Python直譯器不退出引發
SystemExit 當Python直譯器不使用sys.exit()函式引發。如果程式碼沒有被處理,直譯器會退出。

當操作或函式在指定資料型別無效時引發
ValueError 在內建函式對於資料型別,引數的有效型別時引發,但是引數指定了無效值
RuntimeError
當生成的錯誤不屬於任何類別時引發
NotImplementedError
當要在繼承的類來實現,抽象方法實際上沒有實現時引發此異常

在Python中斷言

斷言是一種理智檢查,當程式的測試完成,你可以開啟或關閉。

斷言的最簡單的方法就是把它比作 raise-if 語句 (或者更準確,加 raise-if-not 宣告). 一個表示式進行測試,如果結果出現 false,將引發異常。

斷言是由 assert 語句,在Python中新的關鍵字,在Python1.5版本中引入使用的關鍵字。
程式員常常放置斷言來檢查輸入的有效,或在一個函式呼叫後檢查有效的輸出。

assert 語句

當它遇到一個斷言語句,Python評估計算之後的表示式,希望是 true 值。如果表示式為 false,Python 觸發 AssertionError 異常。

斷言的語法是 -
assert Expression[, Arguments] 

如果斷言失敗,Python使用 ArgumentExpression 作為AssertionError異常的引數。AssertionError異常可以被捕獲,並用 try-except語句處理類似其他異常,但是,如果沒有處理它們將終止該程式並產生一個回溯。

範例

這裡是一個把從開氏度到華氏度的溫度轉換函式。

#!/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 
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:塊不引發異常則程式碼在 else 塊執行

  • else 塊是程式碼的好地方,這不需要 try: 塊的保護

範例

這個例子開啟一個檔案,並寫入內容,檔案處理完全沒有問題 -
#!/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. 

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 子句,但不能同時使用。不能用一個 finally 子句中再使用 else 子句 。

範例

#!/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 塊。如果在 try-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)argument 為異常的引數值。該引數是可選的;如果沒有提供,異常的引數是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