Python 的異常處理

在執(zhí)行程序的過程中昔字,可能會(huì)遇到多多少少的“意外情況”爆袍,比如除數(shù)為 0,文件找不到作郭,變量未聲明等陨囊。解釋器在發(fā)現(xiàn)這些異常錯(cuò)誤后,會(huì)當(dāng)機(jī)立斷終止程序的運(yùn)行夹攒,如果我們想程序繼續(xù)運(yùn)行蜘醋,提高代碼的健壯性,就需要用到異常處理咏尝。

try 和 except

Python 中使用 try 關(guān)鍵字來捕獲異常压语,使用 except 關(guān)鍵字來處理異常啸罢,沒有 catch 關(guān)鍵字。
不進(jìn)行異常處理的情況:

def devide(a,b):
    return a/b
        
devide(1,0)

執(zhí)行 devide 函數(shù)胎食,程序直接掛掉了扰才,拋出一個(gè) ZeroDivisionError 的異常:

Traceback (most recent call last):
  File "C:\Users\Charley\Desktop\py\py.py", line 4, in <module>
    devide(1,0)
  File "C:\Users\Charley\Desktop\py\py.py", line 2, in devide
    return a/b
ZeroDivisionError: division by zero
[Finished in 0.6s with exit code 1]
[shell_cmd: python -u "C:\Users\Charley\Desktop\py\py.py"]
[dir: C:\Users\Charley\Desktop\py]
[path: C:\Python27\;C:\Python27\Scripts;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\nvm;D:\nodejs;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\GtkSharp\2.12\bin;C:\Program Files\MySQL\MySQL Utilities 1.6\;C:\Users\Charley\AppData\Local\Programs\Python\Python35-32\Scripts\;C:\Users\Charley\AppData\Local\Programs\Python\Python35-32\;D:\Git\bin;D:\Sublime Text 3;D:\MinGW\bin\;D:\MinGW\bin\;D:\Microsoft VS Code\bin;D:\Java\jdk 8.0\bin;D:\Android\sdk;C:\Program Files\MySQL\MySQL Server 5.7\bin;]

修改代碼,對(duì) ZeroDivisionError 異常進(jìn)行捕獲處理:

def devide(a,b):
    try:
        return a/b
    except ZeroDivisionError:
        print("除數(shù)不能為零斥季!")
        
devide(1,0)

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

除數(shù)不能為零训桶!

程序沒有掛掉,并對(duì)相應(yīng)的異常進(jìn)行了處理酣倾。

捕獲多個(gè)異常

我們還可以捕獲多個(gè)異常:

def devide(a,b):
    try:
        print(num)
        return a/b
    except ZeroDivisionError:
        print("除數(shù)不能為零!")
    except NameError:
        print("變量不存在谤专!")

devide(1,0)

運(yùn)行結(jié)果:

變量不存在躁锡!

上面的異常處理可以捕獲多個(gè)異常情況,如果觸發(fā)了 ZeroDivisionError 異常置侍,就輸出 除數(shù)不能為零映之! 提示語,如果觸發(fā)了 NameError 異常蜡坊,就輸出 變量不存在杠输! 提示語。
在捕獲多個(gè)異常時(shí)秕衙,也可以進(jìn)行簡寫:

def devide(a,b):
    try:
        print(num)
        return a/b
    except (ZeroDivisionError,NameError):
        print("發(fā)生了一些異常情況蠢甲!請(qǐng)檢查代碼")

devide(1,0)

Python2 中可以將異常直接使用逗號(hào)分隔,Python3 中必須將異常置于元組中据忘。

異常類

除了上面提到的兩種異常鹦牛,Python 中還有許許多多的異常(具體見此),我們可以查看這些異常的數(shù)據(jù)類型:

def devide(a,b):
    try:
        return a/b
    except ZeroDivisionError:
        print(type(ZeroDivisionError))

devide(1,0)

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

<class 'type'>

這些異常都是類勇吊。所有的異常都有一個(gè)共同的父類 Exception曼追,如果我們使用 Exception 來進(jìn)行捕獲,將捕獲到所有的異常情況汉规,使用 as 關(guān)鍵字可以查看具體的異常信息:

def devide(a,b):
    try:
        return a/b
    except Exception as res:
        print(res)

devide(1,0)

運(yùn)行結(jié)果:

division by zero

raise 關(guān)鍵字

raise 關(guān)鍵字用來主動(dòng)觸發(fā)異常:

def devide(a,b):
    try:
        raise NameError
    except Exception:
        print("發(fā)生了一點(diǎn)錯(cuò)誤礼殊!")

devide(1,1)

運(yùn)行結(jié)果:

發(fā)生了一點(diǎn)錯(cuò)誤!

上面我們手動(dòng)觸發(fā)了 NameError 異常针史,同樣可以被捕獲晶伦。

自定義異常

除了系統(tǒng)自帶的異常之外,我們還可以對(duì)異常進(jìn)行自定義悟民,前面說到所有的異常都是類坝辫,因此我們也需要自定義異常類,該類應(yīng)該以 Exception 類作為父類射亏。

class 沒事兒就像搞點(diǎn)事情(Exception):
    def __init__(self,reason):
        self.reason = reason

def devide(a,b):
    try:
        raise 沒事兒就像搞點(diǎn)事情("點(diǎn)事情是誰近忙?")
    except Exception as res:
        print("發(fā)生了一點(diǎn)錯(cuò)誤:%s"%res.reason)

devide(1,1)

運(yùn)行結(jié)果如下:

發(fā)生了一點(diǎn)錯(cuò)誤:點(diǎn)事情是誰竭业?

新建對(duì)象是為了記錄詳細(xì)的異常信息,當(dāng)然也可以直接拋出異常類:

class 沒事兒就像搞點(diǎn)事情(Exception):
    def __init__(self,reason):
        self.reason = reason

def devide(a,b):
    try:
        raise 沒事兒就像搞點(diǎn)事情
    except Exception as res:
        print("發(fā)生了一點(diǎn)錯(cuò)誤")


devide(1,1)

運(yùn)行結(jié)果如下:

發(fā)生了一點(diǎn)錯(cuò)誤

else 關(guān)鍵字

如果沒有出現(xiàn)異常及舍,那么就會(huì)執(zhí)行 else 中的代碼:

def devide(a,b):
    try:
        print(a/b)
    except Exception as res:
        print("發(fā)生了一點(diǎn)錯(cuò)誤:%s"%res)
    else:
        print("嘻嘻未辆,沒有發(fā)生錯(cuò)誤喲!")

devide(1,1)

運(yùn)行結(jié)果如下:

1.0
嘻嘻锯玛,沒有發(fā)生錯(cuò)誤喲咐柜!

finally 關(guān)鍵字

finally 是異常的出口,不管有沒有異常攘残,不管捕獲了多少異常拙友,都會(huì)執(zhí)行 finally 中的語句:

def devide(a,b):
    try:
        print(a/b)
    except Exception as res:
        print("發(fā)生了一點(diǎn)錯(cuò)誤:%s"%res)
    else:
        print("嘻嘻,沒有發(fā)生錯(cuò)誤喲歼郭!")
    finally:
        print("你若安好遗契,便是晴天")

devide(1,1)

運(yùn)行結(jié)果:

1.0
嘻嘻,沒有發(fā)生錯(cuò)誤喲病曾!
你若安好牍蜂,便是晴天

finally 中可以進(jìn)行清理工作,比如關(guān)閉文件泰涂,該操作不論是否發(fā)生異常都應(yīng)該被執(zhí)行了鲫竞,所以應(yīng)該放在 finally 中。

異常傳遞

異常會(huì)在調(diào)用棧中逐層往外傳遞逼蒙,直到被捕獲到為止从绘。內(nèi)層函數(shù)產(chǎn)生了異常,如果自身沒有進(jìn)行處理其做,就將異常傳遞給調(diào)用它的函數(shù)顶考,如果調(diào)用它的函數(shù)也不進(jìn)行處理,再向外傳遞妖泄,直到傳遞給解釋器驹沿,被解釋器所捕獲。

def a():
    print(num)

def b():
    a()

def c():
    try:
        b()
    except Exception as res:
        print(res)

c()

運(yùn)行結(jié)果如下:

name 'num' is not defined

完蹈胡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末渊季,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子罚渐,更是在濱河造成了極大的恐慌却汉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荷并,死亡現(xiàn)場(chǎng)離奇詭異合砂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)源织,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門翩伪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來微猖,“玉大人,你說我怎么就攤上這事缘屹×莅” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵轻姿,是天一觀的道長犁珠。 經(jīng)常有香客問我,道長互亮,這世上最難降的妖魔是什么犁享? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮胳挎,結(jié)果婚禮上饼疙,老公的妹妹穿的比我還像新娘。我一直安慰自己慕爬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布屏积。 她就那樣靜靜地躺著医窿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炊林。 梳的紋絲不亂的頭發(fā)上姥卢,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音渣聚,去河邊找鬼独榴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛奕枝,可吹牛的內(nèi)容都是我干的棺榔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼隘道,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼症歇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谭梗,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤忘晤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后激捏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體设塔,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年闰蛔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痕钢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钞护,死狀恐怖盖喷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤倔矾,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布妄均,位于F島的核電站,受9級(jí)特大地震影響哪自,放射性物質(zhì)發(fā)生泄漏丰包。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一壤巷、第九天 我趴在偏房一處隱蔽的房頂上張望邑彪。 院中可真熱鬧,春花似錦隙笆、人聲如沸锌蓄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘸爽。三九已至,卻和暖如春铅忿,著一層夾襖步出監(jiān)牢的瞬間剪决,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柑潦,地道東北人享言。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像渗鬼,于是被迫代替她去往敵國和親览露。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 處理多個(gè)異常 處理多個(gè)異常譬胎,并不是同時(shí)報(bào)出多個(gè)異常差牛。程序運(yùn)行時(shí),只要遇到一個(gè)異常堰乔,就會(huì)有所反應(yīng)偏化。所以,每次捕獲到的...
    上發(fā)條的樹閱讀 2,116評(píng)論 0 0
  • python中常見的異常 NameError:嘗試訪問一個(gè)未申明的變量 ZeroDivisionError:除數(shù)為...
    junson閱讀 485評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法镐侯,類相關(guān)的語法侦讨,內(nèi)部類的語法,繼承相關(guān)的語法苟翻,異常的語法韵卤,線程的語...
    子非魚_t_閱讀 31,598評(píng)論 18 399
  • 初識(shí),陽光妥妥灑灑 曾想與你長跑 遠(yuǎn)處雪山皚皚 湖水靈動(dòng) 陽光將它們連作一塊 初識(shí)崇猫,秋意濃濃 落葉洋洋灑灑 沉甸甸...
    璇璇的夏天閱讀 237評(píng)論 0 0
  • #白馬聲慢怜俐,我自寫書# 時(shí)間總是這樣,讓人猝不及防在故事的開始它像 在故事的結(jié)尾它又像手中的散沙永遠(yuǎn)握不住邓尤。 ...
    喜歡你哎閱讀 284評(píng)論 0 4