在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 異常處理
基礎(chǔ)
itertools
HTTP 服務(wù)
hashlib
閉包
文件和目錄
類(lèi)
單元測(cè)試
使用 @property
標(biāo)準(zhǔn)模塊
陌生的 metaclass
Base64
進(jìn)程、線程和協(xié)程
讀寫(xiě)二進(jìn)制文件
匿名函數(shù)
輸入和輸出
Click
元組
字符編碼
partial 函數(shù)
參考資料
collections
協(xié)程
類(lèi)和實(shí)例
Python 之旅
定制類(lèi)和魔法方法
常用數(shù)據(jù)類(lèi)型
繼承和多態(tài)
ThreadLocal
HTTP 協(xié)議簡(jiǎn)介
Requests 庫(kù)的使用
讀寫(xiě)文本文件
列表
os 模塊
迭代器 (Iterator)
正則表達(dá)式
集合
上下文管理器
異常處理
你不知道的 super
定義函數(shù)
datetime
資源推薦
字典
slots 魔法
hmac
第三方模塊
進(jìn)程
類(lèi)方法和靜態(tài)方法
函數(shù)參數(shù)
高階函數(shù)
函數(shù)
re 模塊
高級(jí)特性
線程
argparse
生成器
結(jié)束語(yǔ)
字符串
map/reduce/filter
函數(shù)式編程
Celery
裝飾器

異常處理

我們?cè)诰帉?xiě)程序的時(shí)候,經(jīng)常需要對(duì)異常情況做處理。比如,當(dāng)一個(gè)數(shù)試圖除以 0 時(shí),我們需要捕獲這個(gè)異常情況并做處理。你可能會(huì)使用類(lèi)似 if/else 的條件語(yǔ)句來(lái)對(duì)異常情況做判斷,比如,判斷除法的分母是否為零,如果為零,則打印錯(cuò)誤信息。

這在某些簡(jiǎn)單的情況下是可以的,但是,在大多數(shù)時(shí)候,我們應(yīng)該使用 Python 的異常處理機(jī)制。這主要有兩方面的好處:

  • 一方面,你可以選擇忽略某些不重要的異常事件,或在需要的時(shí)候自己引發(fā)異常;
  • 另一方面,異常處理不會(huì)搞亂原來(lái)的代碼邏輯,但如果使用一大堆 if/else 語(yǔ)句,不僅會(huì)沒(méi)效率和不靈活,而且會(huì)讓代碼相當(dāng)難讀;

異常對(duì)象

Python 用異常對(duì)象(exception object)來(lái)表示異常情況。當(dāng)程序在運(yùn)行過(guò)程中遇到錯(cuò)誤時(shí),會(huì)引發(fā)異常。如果異常對(duì)象未被處理或捕捉,程序就會(huì)用所謂的回溯(Traceback,一種錯(cuò)誤信息)終止執(zhí)行。

比如:

>>> 1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

上面的 ZeroDivisionError 就是一個(gè)異常類(lèi),相應(yīng)的異常對(duì)象就是該類(lèi)的實(shí)例。Python 中所有的異常類(lèi)都是從 BaseException 類(lèi)派生的,常見(jiàn)的異常類(lèi)型可以在這里查看。

使用 try/except 捕捉異常

在編寫(xiě)程序的時(shí)候,如果我們知道某段代碼可能會(huì)導(dǎo)致某種異常,而又不希望程序以堆棧跟蹤的形式終止,這時(shí)我們可以根據(jù)需要添加 try/except 或者 try/finally 語(yǔ)句(或者它們的組合)進(jìn)行處理。一般來(lái)說(shuō),有以下使用形式:

try...except...
try...except...else...
try...except...else...finally...
try...except...except...else...finally...
try...finally...

基本形式

捕捉異常的基本形式是 try...except

讓我們看看第一個(gè)例子:

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:
    print 'Error:',e

print 'hello world'

當(dāng) y = 0 時(shí),看看執(zhí)行結(jié)果:

Enter x: 3
Enter y: 0
Error: integer division or modulo by zero
hello world

可以看到,我們的程序正確捕獲了除以零的異常,而且程序沒(méi)有以堆棧跟蹤的形式終止,而是繼續(xù)執(zhí)行后面的代碼,打印出 'hello world'。

多個(gè) except 子句

有時(shí),我們的程序可能會(huì)出現(xiàn)多個(gè)異常,這時(shí)可以用多個(gè) except 子句來(lái)處理這種情況。

讓我們繼續(xù)看第一個(gè)例子,如果 y 輸入的是一個(gè)非數(shù)字的值,就會(huì)產(chǎn)生另外一個(gè)異常:

Enter x: 2
Enter y: 'a'        # y 的輸入是一個(gè)字符
----------------------------------------------------------------------
TypeError                            Traceback (most recent call last)
<ipython-input-209-d4666cfaefb4> in <module>()
      2     x = input('Enter x: ')
      3     y = input('Enter y: ')
----> 4     print x / y
      5 except ZeroDivisionError as e:
      6     print e

TypeError: unsupported operand type(s) for /: 'int' and 'str'

可以看到,當(dāng) y 輸入一個(gè)字符 'a' 之后,程序產(chǎn)生了一個(gè) TypeError 異常,并且終止,這是因?yàn)槲覀兊?except 子句只是捕獲了 ZeroDivisionError 異常,為了能捕獲TypeError 異常,我們可以再加一個(gè) except 子句,完整代碼如下:

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:      # 處理 ZeroDivisionError 異常
    print 'ZeroDivisionError:',e
except TypeError as e:              # 處理 TypeError 異常
    print 'TypeError:',e

print 'hello world'

當(dāng) y 輸入 'a' 時(shí),看看執(zhí)行結(jié)果:

Enter x: 3
Enter y: 'a'
TypeError: unsupported operand type(s) for /: 'int' and 'str'
hello world

捕捉未知異常

事實(shí)上,在編寫(xiě)程序的時(shí)候,我們很難預(yù)料到程序的所有異常情況。比如,對(duì)于第一個(gè)例子,我們可以預(yù)料到一個(gè) ZeroDivisionError 異常,如果細(xì)心一點(diǎn),也會(huì)預(yù)料到一個(gè) TypeError 異常,可是,還是有一些其他情況我們沒(méi)有考慮到,比如在輸入 x 的時(shí)候,我們直接按回車(chē)鍵,這時(shí)又會(huì)引發(fā)一個(gè)異常,程序也會(huì)隨之掛掉:

Enter x:      # 這里輸入回車(chē)鍵
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<string>", line 0

    ^
SyntaxError: unexpected EOF while parsing

那么,我們應(yīng)該怎么在程序捕獲某些難以預(yù)料的異常呢?我們?cè)谏衔恼f(shuō)過(guò),Python 中所有的異常類(lèi)都是從 BaseException 類(lèi)派生的,也就是說(shuō),ZeroDivisionError、SyntaxError 等都是它的子類(lèi),因此,對(duì)于某些難以預(yù)料的異常,我們就可以使用 BaseException 來(lái)捕獲,在大部分情況下,我們也可以使用 Exception 來(lái)捕獲,因?yàn)?Exception 是大部分異常的父類(lèi),可以到這里查看所有異常類(lèi)的繼承關(guān)系。

因此,對(duì)于第一個(gè)例子,我們可以把程序做一些修改,使其更加健壯:

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:      # 捕獲 ZeroDivisionError 異常
    print 'ZeroDivisionError:',e
except TypeError as e:              # 捕獲 TypeError 異常
    print 'TypeError:',e
except BaseException as e:          # 捕獲其他異常
    print 'BaseException:',e

print 'hello world'

注意到,我們把 BaseException 寫(xiě)在了最后一個(gè) except 子句。如果你把它寫(xiě)在了第一個(gè) except 子句,由于 BaseException 是所有異常的父類(lèi),那么程序的所有異常都會(huì)被第一個(gè) except 子句捕獲。

else 子句

我們可以在 except 子句后面加一個(gè) else 子句。當(dāng)沒(méi)有異常發(fā)生時(shí),會(huì)自動(dòng)執(zhí)行 else 子句。

對(duì)第一個(gè)例子,加入 else 子句:

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:
    print 'ZeroDivisionError:',e
except TypeError as e:
    print 'TypeError:',e
except BaseException as e:
    print 'BaseException:',e
else:
    print 'no error!'

print 'hello world'

看看執(zhí)行結(jié)果:

Enter x: 6
Enter y: 2
3
no error!
hello world

finally 子句

finally 子句不管有沒(méi)有出現(xiàn)異常都會(huì)被執(zhí)行。

看看例子:

try:
    x = 1/0
    print x
finally:
    print 'DONE'

執(zhí)行結(jié)果:

DONE
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero

再看一個(gè)例子:

try:
    x = 1/0
    print x
except ZeroDivisionError as e:
    print 'ZeroDivisionError:',e
finally:
    print 'DONE'

執(zhí)行結(jié)果:

ZeroDivisionError: integer division or modulo by zero
DONE

使用 raise 手動(dòng)引發(fā)異常

有時(shí),我們使用 except 捕獲了異常,又想把異常拋出去,這時(shí)可以使用 raise 語(yǔ)句。

看看例子:

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:
    print 'ZeroDivisionError:',e
except TypeError as e:
    print 'TypeError:',e
except BaseException as e:
    print 'BaseException:',e
    raise                           # 使用 raise 拋出異常
else:
    print 'no error!'

print 'hello world'

運(yùn)行上面代碼,當(dāng) x 輸入一個(gè)回車(chē)鍵時(shí),錯(cuò)誤會(huì)被打印出來(lái),并被拋出:

Enter x:    # 這里輸入回車(chē)鍵
BaseException: unexpected EOF while parsing (<string>, line 0)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<string>", line 0

    ^
SyntaxError: unexpected EOF while parsing

上面的 raise 語(yǔ)句是不帶參數(shù)的,它會(huì)把當(dāng)前錯(cuò)誤原樣拋出。事實(shí)上,我們也創(chuàng)建自己的異常類(lèi),并拋出自定義的異常。

創(chuàng)建自定義的異常類(lèi)需要從 Exception 類(lèi)繼承,可以間接繼承或直接繼承,也就是可以繼承其他的內(nèi)建異常類(lèi)。比如:

# 自定義異常類(lèi)
class SomeError(Exception):
    pass

try:
    x = input('Enter x: ')
    y = input('Enter y: ')
    print x / y
except ZeroDivisionError as e:
    print 'ZeroDivisionError:',e
except TypeError as e:
    print 'TypeError:',e
except BaseException as e:
    print 'BaseException:',e
    raise SomeError('invalid value')    # 拋出自定義的異常
else:
    print 'no error!'

print 'hello world'

運(yùn)行上面代碼,當(dāng) x 輸入一個(gè)回車(chē)鍵時(shí),錯(cuò)誤被打印出來(lái),并拋出我們自定義的異常:

Enter x: 
BaseException: unexpected EOF while parsing (<string>, line 0)
----------------------------------------------------------------------
SomeError                            Traceback (most recent call last)
<ipython-input-20-66060b472f91> in <module>()
     12 except BaseException as e:
     13     print 'BaseException:',e
---> 14     raise SomeError('invalid value')
     15 else:
     16     print 'no error!'

SomeError: invalid value

小結(jié)

  • Python 中所有的異常類(lèi)都是從 BaseException 類(lèi)派生的。
  • 通過(guò) try/except 來(lái)捕捉異常,可以使用多個(gè) except 子句來(lái)分別處理不同的異常。
  • else 子句在主 try 塊沒(méi)有引發(fā)異常的情況下被執(zhí)行。
  • finally 子句不管是否發(fā)生異常都會(huì)被執(zhí)行。
  • 通過(guò)繼承 Exception 類(lèi)可以創(chuàng)建自己的異常類(lèi)。

參考資料

上一篇:map/reduce/filter下一篇:進(jìn)程