錯誤和異常(2)

2018-02-24 15:48 更新

try...except...是處理異常的基本方式。在原來的基礎上,還可有擴展。

處理多個異常

處理多個異常,并不是因為同時報出多個異常。程序在運行中,只要遇到一個異常就會有反應,所以,每次捕獲到的異常一定是一個。所謂處理多個異常的意思是可以容許捕獲不同的異常,有不同的except子句處理。

#!/usr/bin/env python
# coding=utf-8

while 1:
    print "this is a division program."
    c = raw_input("input 'c' continue, otherwise logout:")
    if c == 'c':
        a = raw_input("first number:")
        b = raw_input("second number:")
        try:
            print float(a)/float(b)
            print "*************************"
        except ZeroDivisionError:
            print "The second number can't be zero!"
            print "*************************"
        except ValueError:
            print "please input number."
            print "************************"
    else:
        break

將上節(jié)的一個程序進行修改,增加了一個except子句,目的是如果用戶輸入的不是數(shù)字時,捕獲并處理這個異常。測試如下:

$ python 21701.py 
this is a division program.
input 'c' continue, otherwise logout:c
first number:3
second number:"hello"        #輸入了一個不是數(shù)字的東西
please input number.         #對照上面的程序,捕獲并處理了這個異常
************************
this is a division program.
input 'c' continue, otherwise logout:c
first number:4
second number:0
The second number can't be zero!
*************************
this is a division program.
input 'c' continue, otherwise logout:4
$

如果有多個except,在try里面如果有一個異常,就轉(zhuǎn)到相應的except子句,其它的忽略。如果except沒有相應的異常,該異常也會拋出,不過這是程序就要中止了,因為異?!案〕觥背绦蝽敳?。

除了用多個except之外,還可以在一個except后面放多個異常參數(shù),比如上面的程序,可以將except部分修改為:

except (ZeroDivisionError, ValueError):
    print "please input rightly."
    print "********************"

運行的結(jié)果就是:

$ python 21701.py 
this is a division program.
input 'c' continue, otherwise logout:c
first number:2
second number:0           #捕獲異常
please input rightly.
********************
this is a division program.
input 'c' continue, otherwise logout:c
first number:3
second number:a           #異常
please input rightly.
********************
this is a division program.
input 'c' continue, otherwise logout:d
$

需要注意的是,except后面如果是多個參數(shù),一定要用圓括號包裹起來。否則,后果自負。

突然有一種想法,在對異常的處理中,前面都是自己寫一個提示語,發(fā)現(xiàn)自己寫的不如內(nèi)置的異常錯誤提示更好。希望把它打印出來。但是程序還能不能中斷。python提供了一種方式,將上面代碼修改如下:

while 1:
    print "this is a division program."
    c = raw_input("input 'c' continue, otherwise logout:")
    if c == 'c':
        a = raw_input("first number:")
        b = raw_input("second number:")
        try:
            print float(a)/float(b)
            print "*************************"
        except (ZeroDivisionError, ValueError), e:
            print e
            print "********************"
    else:
        break

運行一下,看看提示信息。

$ python 21702.py 
this is a division program.
input 'c' continue, otherwise logout:c
first number:2
second number:a                         #異常
could not convert string to float: a
********************
this is a division program.
input 'c' continue, otherwise logout:c
first number:2
second number:0                         #異常
float division by zero
********************
this is a division program.
input 'c' continue, otherwise logout:d
$

在python3.x中,常常這樣寫:except (ZeroDivisionError, ValueError) as e:

以上程序中,之處理了兩個異常,還可能有更多的異常呢?如果要處理,怎么辦?可以這樣:execpt:或者except Exception, e,后面什么參數(shù)也不寫就好了。

else子句

有了try...except...,在一般情況下是夠用的,但總有不一般的時候出現(xiàn),所以,就增加了一個else子句。其實,人類的自然語言何嘗不是如此呢?總要根據(jù)需要添加不少東西。

>>> try:
...     print "I am try"
... except:
...     print "I am except"
... else:
...     print "I am else"
... 
I am try
I am else

這段演示,能夠幫助讀者理解else的執(zhí)行特點。如果執(zhí)行了try,則except被忽略,但是else被執(zhí)行。

>>> try:
...     print 1/0
... except:
...     print "I am except"
... else:
...     print "I am else"
... 
I am except

這時候else就不被執(zhí)行了。

理解了else的執(zhí)行特點,可以寫這樣一段程序,還是類似于前面的計算,只不過這次要求,如果輸入的有誤,就不斷要求從新輸入,知道輸入正確,并得到了結(jié)果,才不再要求輸入內(nèi)容,程序結(jié)束。

在看下面的參考代碼之前,讀者是否可以先自己寫一段呢?并調(diào)試一下,看看結(jié)果如何。

#!/usr/bin/env python
# coding=utf-8
while 1:
    try:
        x = raw_input("the first number:")
        y = raw_input("the second number:")

        r = float(x)/float(y)
        print r
    except Exception, e:
        print e
        print "try again."
    else:
        break

先看運行結(jié)果:

$ python 21703.py
the first number:2
the second number:0        #異常,執(zhí)行except
float division by zero
try again.                 #循環(huán)
the first number:2
the second number:a        #異常 
could not convert string to float: a
try again.
the first number:4
the second number:2        #正常,執(zhí)行try
2.0                        #然后else:break,退出程序
$

相當滿意的執(zhí)行結(jié)果。

需要對程序中的except簡單說明,這次沒有像前面那樣寫,而是except Exception, e,意思是不管什么異常,這里都會捕獲,并且傳給變量e,然后用print e把異常信息打印出來。

finally

finally子句,一聽這個名字,就感覺它是做善后工作的。的確如此,如果有了finally,不管前面執(zhí)行的是try,還是except,它都要執(zhí)行。因此一種說法是用finally用來在可能的異常后進行清理。比如:

>>> x = 10

>>> try:
...     x = 1/0
... except Exception, e:
...     print e
... finally:
...     print "del x"
...     del x
... 
integer division or modulo by zero
del x

看一看x是否被刪除?

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

當然,在應用中,可以將上面的各個子句都綜合起來使用,寫成如下樣式:

try:
    do something
except:
    do something
else:
    do something
finally
    do something

和條件語句相比

try...except...在某些情況下能夠替代if...else..的條件語句。這里我無意去比較兩者的性能,因為看到有人討論這個問題。我個人覺得這不是主要的,因為它們之間性能的差異不大。主要是你的選擇。一切要根據(jù)實際情況而定,不是說用一個就能包打天下。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號