錯誤和異常
程序運行時有兩種可以分辨的錯誤: syntax error 和 exception , 按中文來說, 就是語法錯誤和異常。
語法錯誤
語法錯誤也就是解析錯誤,是我們最優可能遇到的錯誤。
while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax
在這個例子中, 錯誤是在 print()
函數這里被發現的, 因為在它之前少了一個冒號 (':'
). 文件的名稱與行號會被打印出來, 以便於你能找到一個腳本中導致錯誤的地方。
異常
即使語法沒有錯誤,在運行時也會有報錯,這樣的報錯我們叫做異常:大多數異常並不會被程序處理, 不過, 導致錯誤的信息會被顯示出來。
print(10 * (1/0)) Traceback (most recent call last): File "/Users/hadoop/Documents/Python_workspace/python_3.X/Exception.py", line 3, in <module> print(10 * (1/0)) ZeroDivisionError: division by zero
Built-in Exceptions :列出了內建的異常和它們的意義。
異常處理
try
語句像下面這樣使用.
- 首先, try clause (在
try
和except
之間的語句) 將被執行. - 如果沒有異常發生, except clause 將被跳過,
try
語句就算執行完了. - 如果在 try 語句執行時, 出現了一個異常, 該語句的剩下部分將被跳過. 然后如果它的類型匹配到了
except
后面的異常名, 那么該異常的語句將被執行, 而執行完后會運行try
后面的問題. - 如果一個異常發生時並沒有匹配到 except 語句中的異常名, 那么它就被傳到
try
語句外面; 如果沒有處理, 那么它就是 unhandled exception 並且將會像前面那樣給出一個消息然后執行.
while True: try: nu = int(input("please input a number:")) break except ValueError: print("valid number!") please input a number:a valid number! please input a number:a valid number! please input a number:1
一個 try
語句可以有多於一條的 except 語句, 用以指定不同的異常. 但至多只有一個會被執行. Handler 僅僅處理在相應 try 語句中的異常, 而不是在同一 try
語句中的其他 Handler. 一個異常的語句可以同時包括多個異常名, 但需要用括號括起來, 比如:
except (RuntimeError, TypeError, NameError): pass
最后的異常段可以忽略異常的名字, 用以處理其他的情況. 使用這個時需要特別注意, 因為它很容易屏蔽了程序中的錯誤! 它也用於輸出錯誤消息, 然后重新產生異常 (讓調用者處理該異常):
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except IOError as err: print("I/O error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") except: print("Unexpected error:", sys.exc_info()[0]) raise
try
... except
語句可以有一個可選的 else 語句, 在這里, 必須要放在所有 except 語句后面. 它常用於沒有產生異常時必須執行的語句. 例如:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print('cannot open', arg) else: print(arg, 'has', len(f.readlines()), 'lines') f.close()
使用 else
比額外的添加代碼到 try
中要好, 因為這樣可以避免偶然的捕獲一個異常, 但卻不是由於我們保護的代碼所拋出的.
當一個異常發生了, 它可能有相關的值, 這也就是所謂的異常的參數. 該參數是否出現及其類型依賴於異常的類型.
在 except 語句中可以在異常名后指定一個變量. 變量會綁定值這個異常的實例上, 並且把參數存於 instance.args
. 為了方便, 異常的實例會定義 __str__()
來直接將參數打印出來, 而不用引用 .args
. 當然也可以在產生異常前, 首先實例化一個異常, 然后把需要的屬性綁定給它.
try: raise Exception('spam', 'eggs') except Exception as inst: print(type(inst)) # the exception instance print(inst.args) # arguments stored in .args print(inst) # __str__ allows args to be printed directly, # but may be overridden in exception subclasses x, y = inst.args # unpack args print('x =', x) <class 'Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
如果一個異常有參數, 它們將作為異常消息的最后一部分打印出來.
異常的 handler 處理的異常, 不僅僅是 try 語句中那些直接的異常, 也可以是在此處調用的函數所產生的異常。