語法錯誤
語法錯誤又稱解析錯誤,可能是你在學習Python 時最容易遇到的錯誤:
>>> while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax
解析器會輸出出現語法錯誤的那一行,並顯示一個“箭頭”,指向這行裏面檢測到第一個錯誤。 錯誤是由箭頭指示的位置 上面 的 token 引起的(或者至少是在這裏被檢測出的):在示例中,在 print() 這個函數中檢測到了錯誤,因爲在它前面少了個冒號 (’:’) 。文件名和行號也會被輸出,以便輸入來自腳本文件時你能知道去哪檢查。
異常
即使語句或表達式在語法上是正確的,但在嘗試執行時,它仍可能會引發錯誤。 在執行時檢測到的錯誤被稱爲異常,異常不一定會導致嚴重後果:你將很快學會如何在Python程序中處理它們。 但是,大多數異常並不會被程序處理,此時會顯示如下所示的錯誤信息:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
處理異常
可以編寫處理所選異常的程序。請看下面的例子,它會要求用戶一直輸入,直到輸入的是一個有效的整數,但允許用戶中斷程序(使用 Control-C 或操作系統支持的其他操作);請注意用戶引起的中斷可以通過引發 KeyboardInterrupt 異常來指示。:
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
try 語句的工作原理如下。
首先,執行 try 子句 (try 和 except 關鍵字之間的(多行)語句)。
如果沒有異常發生,則跳過 except 子句 並完成 try 語句的執行。
如果在執行try 子句時發生了異常,則跳過該子句中剩下的部分。然後,如果異常的類型和 except 關鍵字後面的異常匹配,則執行 except 子句 ,然後繼續執行 try 語句之後的代碼。
如果發生的異常和 except 子句中指定的異常不匹配,則將其傳遞到外部的 try 語句中;如果沒有找到處理程序,則它是一個 未處理異常,執行將停止並顯示如上所示的消息。
一個 try 語句可能有多個 except 子句,以指定不同異常的處理程序。 最多會執行一個處理程序。 處理程序只處理相應的 try 子句中發生的異常,而不處理同一 try 語句內其他處理程序中的異常。 一個 except 子句可以將多個異常命名爲帶括號的元組,例如:
... except (RuntimeError, TypeError, NameError):
... pass
如果發生的異常和 except 子句中的類是同一個類或者是它的基類,則異常和except子句中的類是兼容的(但反過來則不成立 — 列出派生類的except 子句與基類兼容)。例如,下面的代碼將依次打印 B, C, D
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
請注意如果 except 子句被顛倒(把 except B 放到第一個),它將打印 B,B,B — 即第一個匹配的 except 子句被觸發。
最後的 except 子句可以省略異常名,以用作通配符。但請謹慎使用,因爲以這種方式很容易掩蓋真正的編程錯誤!它還可用於打印錯誤消息,然後重新引發異常(同樣允許調用者處理異常):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS 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 子句後面。對於在try 子句 不引發異常時必須執行的代碼來說很有用。例如:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
拋出異常
raise 語句允許程序員強制發生指定的異常。例如:
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere
raise 唯一的參數就是要拋出的異常。這個參數必須是一個異常實例或者是一個異常類(派生自 Exception 的類)。如果傳遞的是一個異常類,它將通過調用沒有參數的構造函數來隱式實例化:
raise ValueError # shorthand for 'raise ValueError()'
如果你需要確定是否引發了異常但不打算處理它,則可以使用更簡單的 raise 語句形式重新引發異常
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: HiThere