python中錯誤和異常

語法錯誤

語法錯誤又稱解析錯誤,可能是你在學習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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章