您當前的位置:首頁 > 文化

[1] Python異常處理

作者:由 Lil Jun 發表于 文化時間:2018-02-10

1. 概述

在本文中我會介紹關於在Python中如何處理各種錯誤異常。首先我們來看一下我們在上一篇中擬定的學習計劃,加粗體代表我們已經介紹的內容,斜體代表新增內容。

異常處理

檔案的讀寫

正則表示式

操作檔案和目錄

深複製和淺複製

面向物件的程式設計

變數(擴充套件介紹)

二進位制、八進位制和十六進位制(包括ASCII)

迭代、生成和遞迴

高階函式map

匿名函式lambda

影象處理(運用numpy)

2. 異常型別

異常有各種各樣,比如我們輸入

a

=

1

/

0

肯定是會報錯的,0不能作為除數,還比如:

a

=

0

1

2

3

4

a

100

也肯定會報錯,因為這個數列壓根就沒有第100位。

報錯的時候,我們通常會看到PyCharm下面執行區內紅紅的一堆字提示錯誤。

我們能見到的異常型別有各種各樣,

BaseException

+—— SystemExit

+—— KeyboardInterrupt

+—— GeneratorExit

+—— Exception

+—— StopIteration

+—— StopAsyncIteration

+—— ArithmeticError

| +—— FloatingPointError

| +—— OverflowError

| +—— ZeroDivisionError

+—— AssertionError

+—— AttributeError

+—— BufferError

+—— EOFError

+—— ImportError

| +—— ModuleNotFoundError

+—— LookupError

| +—— IndexError

| +—— KeyError

+—— MemoryError

+—— NameError

| +—— UnboundLocalError

+—— OSError

| +—— BlockingIOError

| +—— ChildProcessError

| +—— ConnectionError

| | +—— BrokenPipeError

| | +—— ConnectionAbortedError

| | +—— ConnectionRefusedError

| | +—— ConnectionResetError

| +—— FileExistsError

| +—— FileNotFoundError

| +—— InterruptedError

| +—— IsADirectoryError

| +—— NotADirectoryError

| +—— PermissionError

| +—— ProcessLookupError

| +—— TimeoutError

+—— ReferenceError

+—— RuntimeError

| +—— NotImplementedError

| +—— RecursionError

+—— SyntaxError

| +—— IndentationError

| +—— TabError

+—— SystemError

+—— TypeError

+—— ValueError

| +—— UnicodeError

| +—— UnicodeDecodeError

| +—— UnicodeEncodeError

| +—— UnicodeTranslateError

+—— Warning

+—— DeprecationWarning

+—— PendingDeprecationWarning

+—— RuntimeWarning

+—— SyntaxWarning

+—— UserWarning

+—— FutureWarning

+—— ImportWarning

+—— UnicodeWarning

+—— BytesWarning

+—— ResourceWarning

這些都是在官網文件上覆制貼上下來的,這裡面的比如NameError,指的是我們用了沒有定義的變數名,FileNotFoundError指的是要讀取的檔案不存在,ZeroDivisionError指的是我們除以了一個零。大家可以點選下面的連結來了解各種錯誤異常。

3. 處理異常

如果我們的程式碼有錯,程式就會在遇見第一個錯誤時報錯並停止執行,為了讓程式能夠平穩執行,不被錯誤所打擾,這裡我們需要知道如何處理:

try

# Your code

except

# What to do with the exception/error

我們需要在我們可能產生錯誤的程式碼外面套上try…except語句。try下面直接寫上我們原先的程式碼,except下面寫上我們如果遇到程式異常後該怎麼做,這樣的話我們程式就能遇到錯誤後依舊平穩執行。

while

True

try

x

=

int

input

‘Please enter a number: ’

))

break

except

print

‘That was no valid number。’

我們執行這段程式碼,我們可以看到如果我們輸入不是整數的話,就會輸出except下面的那句話,但是程式並沒有“異常終止”,如果我們輸入的是整數的話,程式就會安靜地執行結束。

可以看到,錯誤產生時while迴圈並未被break打斷,可以得知

異常被捕捉到後馬上就會忽略之後的內容,並且直接跳至except。

當然我們可以更清晰一點:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

break

except

ValueError

print

‘That was no valid number。’

因為int後面的不能轉換為整數時會歸為ValueError。如果我們不知道是何種異常時,我們操作方法可以是:

只寫except,

執行沒有try…except的語句,故意輸入錯誤,看紅字顯示是什麼再回來改

用Exception代替所有可能性,如下

while

True

try

x

=

int

input

‘Please enter a number: ’

))

break

except

Exception

print

‘That was no valid number。’

當然,你也可以用BaseException,這裡要知道所有的基本錯誤都歸於BaseException下,且絕大部分錯誤是歸於Exception下的。

4. 多種異常

當然,我們的程式碼有時候會因各種原因碰見多種異常,比如

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

Exception

print

‘Some error occurred。’

如果使用者輸入非整數,就會跑except去,如果使用者輸入是0,0不能做除數,也會跑except去。這是我們可以這樣:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

ValueError

print

‘That was no valid number。’

except

ZeroDivisionError

print

‘100 / 0 is invalid。’

這樣我們就能在執行時區分到底錯在哪裡了。當然由於try發現異常後會去找

第一個

能處理此異常的except,在這裡兩個except不相關,能交換位置。

而下面的程式碼:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

Exception

print

‘Exception!’

except

ValueError

print

‘That was no valid number。’

except

ZeroDivisionError

print

‘100 / 0 is invalid。’

這裡它只會看第一個except,發現錯誤後永遠只會輸出Exception,原因是Exception包含了ValueError和ZeroDivisionError,try發現異常後看到第一句except能處理,就把異常交給第一個except,自動忽略後面的。

我們還可以如此處理多種異常:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

ZeroDivisionError

ValueError

):

print

‘Exception!’

用括號括起來,裡面能寫幾個寫幾個,這樣的話我們如果遇見括號裡面任意一種異常,就能執行此except。

5. 異常所攜帶的資訊

通常異常中會帶有資訊,我們可以賦予異常一個變數名以輸出具體資訊:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

ZeroDivisionError

ValueError

as

e

print

e

當然不一定非得命名為e,如果我們輸入0,則會輸出:

division by zero

而如果我們輸入非整數,而是其他字元的話,比如我輸入了apple,則會輸出:

invalid literal for int() with base 10: ‘apple’

這些都是這寫異常所攜帶的資訊。

6. finally和else語句

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

break

except

ZeroDivisionError

ValueError

as

e

print

e

finally

print

‘Goodbye!’

也就是說不管有沒有錯,在執行完上述的程式碼後,一定會執行finally內部的程式碼。如果我們輸入的是0或者非整數,會輸出錯誤資訊後帶著輸出Goodbye然後繼續迴圈會try,如果我們輸入正確,執行沒有錯,while True被break順利終止了,還是會繼續finally內部的程式碼,輸出Goodbye。

while

True

try

x

=

int

input

‘Please enter a number: ’

))

print

100

/

x

except

ZeroDivisionError

ValueError

as

e

print

e

else

print

‘Goodbye!’

break

else語句只有在try下面沒有錯的情況下才會執行,注意我把break移到else下面了,我們可以把它看作是try內部內容的延伸。

7. raise語句

當然,我們在自己寫碼的時候,也會需要在某些場合

輸出異常

。比如我們認為負整數不是整數,那麼輸入後,我們可以手動輸出此異常。

while

True

try

x

=

int

input

‘Please enter a number: ’

))

if

x

<

0

raise

ValueError

break

except

ValueError

as

e

print

e

但是由於這個ValueError是我們自己輸出的,這麼寫我們並不會看到其攜帶資訊,我們可以這麼做讓其攜帶自定義資訊:

while

True

try

x

=

int

input

‘Please enter a number: ’

))

if

x

<

0

raise

ValueError

‘Negative number is not allowed’

break

except

ValueError

as

e

print

e

輸出測試:

Please enter a number: y

invalid literal for int() with base 10: ‘y’

Please enter a number: -9

Negative number is not allowed

Please enter a number: 0

輸入0,沒有錯誤,程式順利結束。

標簽: print  number  try  except  int