Python學(xué)習(xí)

第九天

今天我們來說下Python中的異常,以及如何去處理異常。我們在程序編碼中難免會碰到異常夺巩,今天我們就要來簡要說明什么是異常货葬,如何處理異常。

1劲够、異常的定義

不論是Python語言震桶、Java語言以及其他任何語言,程序在執(zhí)行的過程中難免會產(chǎn)生的錯誤征绎,這些錯誤都可以稱之為異常蹲姐。比如列表索引越界、打開不存在的文件等人柿。
就如同下面兩行代碼:

print(str1)
# name 'str1' is not defined
open('error.txt','r')
# No such file or directory: 'error.txt'

2柴墩、異常處理

程序中出現(xiàn)異常是難免的,發(fā)生異常時我們需要捕獲處理它凫岖,否則程序會終止執(zhí)行江咳。
如下代碼:

#控制臺輸入兩個數(shù)字 求商
print('程序開始')
num1 = int(input('請輸入除數(shù)'))
num2 = int(input('請輸入被除數(shù)'))
print(str(num1)+'除以'+str(num2)+'的結(jié)果是',str(num1/num2))
print('程序結(jié)束')

上述這段代碼其實就是存在問題的,比如我在獲得數(shù)字num1的時候輸入的內(nèi)容不可以轉(zhuǎn)換為int(比如你輸入wasd),這個時候就出現(xiàn)異常了哥放。
ValueError: invalid literal for int() with base 10: 'wasd'
其實就是將非數(shù)字字符串轉(zhuǎn)換為整型出現(xiàn)的異常歼指;
如果你在獲得num2的時候,如果輸入了0也會出現(xiàn)異常甥雕,
ZeroDivisionError: division by zero
其實就是除以0的原因?qū)е碌摹?br> 并且我們發(fā)現(xiàn)上述兩種異常任何一種異常出現(xiàn)踩身,我們的程序就停止了,并且程序沒有往下執(zhí)行社露,因為我們在控制臺看不到最后一行print的輸出挟阻。
這時候就需要我們異常處理了。

2.1峭弟、異常類

在Python中附鸽,所有異常都是基類Exception的成員,它們都定義在exceptions模塊中瞒瘸。
如果這個異常對象沒有進(jìn)行處理和捕捉坷备,程序就會用所謂的回溯(traceback,一種錯誤信息)終止執(zhí)行挨务,這些信息包括錯誤的名稱(例如NameError)击你、原因和錯誤發(fā)生的行號。下面簡單說下我們經(jīng)常遇見的幾個異常:
1谎柄、NameError
嘗試訪問一個未聲明的變量丁侄,會引發(fā)NameError。

print(str1)
# NameError: name 'str1' is not defined

2朝巫、ZeroDivisionError
當(dāng)除數(shù)為零的時候鸿摇,會引發(fā)ZeroDivisionError異常。

a = 10/0
print(a)
# ZeroDivisionError: division by zero

**3劈猿、SyntaxError **
當(dāng)解釋器發(fā)現(xiàn)語法錯誤時拙吉,會引發(fā)SyntaxError異常潮孽。

a = 10
if a == 10
    print('賓果!')
# SyntaxError: invalid syntax

4筷黔、IndexError
當(dāng)使用序列中不存在的索引時往史,會引發(fā)IndexError異常。

list = [1,2,3,4]
a = list[4]
print(a)
# IndexError: list index out of range

5佛舱、KeyError
當(dāng)使用映射中不存在的鍵時椎例,會引發(fā)KeyError異常。

mydict = {'name':'張三','age':18}
address = mydict['address']
print(address)
# KeyError: 'address'

**6请祖、FileNotFoundError **
試圖打開不存在的文件時订歪,會引發(fā)FileNotFoundError。

file = open('a.txt','r')
# FileNotFoundError: [Errno 2] No such file or directory: 'a.txt'

7肆捕、AttributeError
當(dāng)嘗試訪問未知對象屬性時刷晋,會引發(fā)AttributeError異常。

class Settings():
   def _init_(self):
       self.scren_width=1200
       self.screen_height=800
       self.bg_color=(230,230,230)
if __name__ == '__main__':
   a = Settings()
   print(a.scren_width)
# AttributeError: 'Settings' object has no attribute 'scren_width'

2.2慎陵、異常處理

在python中眼虱,try-except語句定義了監(jiān)控異常的一段代碼,并提供了處理異常的機制荆姆。

1蒙幻、捕獲指定異常

try:
        # 可能會出現(xiàn)異常的語句塊
except <異常種類>:
        # 異常處理代碼
print('程序開始')
try:
    a = 10/0
    print(a)
except ZeroDivisionError as e:
    print('捕獲異常-零不可以是除數(shù)',e)
print('程序繼續(xù)執(zhí)行')
# 程序開始
# 捕獲異常-零不可以是除數(shù) division by zero
# 程序繼續(xù)執(zhí)行

注意,exception后捕獲的異常必須和try代碼塊中出現(xiàn)的異常種類一致胆筒,才可以捕獲,否則依然會出現(xiàn)異常诈豌,影響其后代碼的執(zhí)行仆救。

print('程序開始')
try:
    a = 10/0
    print(a)
except FileNotFoundError as e:
    print('捕獲異常-文件找不到',e)
print('程序繼續(xù)執(zhí)行')
# ZeroDivisionError: division by zero

2、捕獲多個異常

捕獲多個異常有兩種方式矫渔,第一種是一個except同時處理多個異常彤蔽,不區(qū)分優(yōu)先級。

try:
     # 可能會出現(xiàn)異常的語句塊
except (<異常名1>, <異常名2>, ...): 
      # 異常處理代碼
print('程序開始')
try:
   num1 = int(input('請輸入除數(shù)'))
   num2 = int(input('請輸入被除數(shù)'))
   print(str(num1)+'除以'+str(num2)+'的結(jié)果是',str(num1/num2))
except (ZeroDivisionError,ValueError):
   print('出現(xiàn)異常了')
print('程序繼續(xù)執(zhí)行')

還有第二種方式庙洼,是區(qū)分優(yōu)先級的顿痪。

try:
        # 可能會出現(xiàn)異常的語句塊
except <異常種類1>:
        # 異常處理代碼1
except <異常種類2>:
        # 異常處理代碼2
except <異常種類3>:
        # 異常處理代碼3
print('程序開始')
try:
   num1 = int(input('請輸入除數(shù)'))
   num2 = int(input('請輸入被除數(shù)'))
   print(str(num1)+'除以'+str(num2)+'的結(jié)果是',str(num1/num2))
except ZeroDivisionError as e1:
   print('出現(xiàn)異常了',e1)
except ValueError as e2:
   print('出現(xiàn)異常了',e2)
print('程序繼續(xù)執(zhí)行')

3、異常中的else

如果try語句沒有捕獲到任何的錯誤信息油够,就不再執(zhí)行任何except語句蚁袭,而是會執(zhí)行else語句。

try:
        # 可能會出現(xiàn)異常的語句塊
except <異常種類1>:
        # 異常處理代碼1
except <異常種類2>:
        # 異常處理代碼2
except <異常種類3>:
        # 異常處理代碼3
else:
    # try語句中沒有異常則執(zhí)行此段代碼
import  os
print('程序開始執(zhí)行')
try:
    wfile = open('2.txt','w',encoding='utf-8')
    wfile.write('這是測試文件寫入的內(nèi)容')
except IOError as e:
    print('IO異常',2)
else:
    print('內(nèi)容寫入成功')
    wfile.close()
print('程序繼續(xù)執(zhí)行')
# 程序開始執(zhí)行
# 內(nèi)容寫入成功
# 程序繼續(xù)執(zhí)行

4石咬、捕獲所有的異常

當(dāng)程序中出現(xiàn)大量異常時揩悄,捕獲這些異常是非常麻煩的。這時鬼悠,我們可以在except子句中不指明異常的類型删性,這樣亏娜,不管發(fā)生何種類型的異常,都會執(zhí)行except里面的處理代碼蹬挺。

print('程序開始')
try:
   num1 = int(input('請輸入除數(shù)'))
   num2 = int(input('請輸入被除數(shù)'))
   print(str(num1)+'除以'+str(num2)+'的結(jié)果是',str(num1/num2))
except:
   print('出現(xiàn)異常了')
print('程序繼續(xù)執(zhí)行')

5维贺、終止行為(finally)

在程序中,無論是否捕捉到異常巴帮,都必須要執(zhí)行某件事情幸缕,例如關(guān)閉文件、釋放鎖等晰韵,這時可以提供finally語句處理发乔。通常情況下,finally用于釋放資源雪猪。

str = 'hello python'
try:
    a = int(str)
except IndexError as e1:
    print('出現(xiàn)異常',e1)
except KeyError as e2:
    print('出現(xiàn)異常',e2)
except ValueError as e3:
    print('出現(xiàn)異常',e3)
else:
    print('try內(nèi)沒有異常')
finally:
    print('無論異常與否,都會執(zhí)行我')

3栏尚、raise語句

python是否可以在程序的指定位置手動拋出一個異常?答案是肯定的只恨,python 允許我們在程序中手動設(shè)置異常译仗,使用 raise 語句即可。類似Java中的throw官觅。
語法:raise [exceptionName [(reason)]]
其中纵菌,用 [] 括起來的為可選參數(shù),其作用是指定拋出的異常名稱休涤,以及異常信息的相關(guān)描述咱圆。如果可選參數(shù)全部省略,則 raise 會把當(dāng)前錯誤原樣拋出功氨;如果僅省略 (reason)序苏,則在拋出異常時,將不附帶任何的異常描述信息捷凄。
簡而言之就是使用raise語句能顯示地觸發(fā)異常忱详。
格式如下:
1、raise 異常類名 引發(fā)指定異常類的實例
2跺涤、raise 異常類對象 引發(fā)指定異常類的實例
3匈睁、raise 重新引發(fā)剛剛發(fā)生的異常

3.1、使用類名引發(fā)異常

print('程序開始執(zhí)行')
try:
    a = input('請輸入一個數(shù)字')
    #判斷用戶輸入的是否為數(shù)字
    if(not a.isdigit()):
        raise ValueError("輸入的必須是數(shù)字") #人為扔出異常
except ValueError as e:
    print("引發(fā)異常:",repr(e))
print('程序繼續(xù)執(zhí)行')
# 程序開始執(zhí)行
# 請輸入一個數(shù)字wasd
# 引發(fā)異常: ValueError('輸入的必須是數(shù)字')
# 程序繼續(xù)執(zhí)行

3.2桶错、使用異常類的實例引發(fā)異常

print('程序開始執(zhí)行')
try:
    a = input('請輸入一個數(shù)字')
    #判斷用戶輸入的是否為數(shù)字
    if(not a.isdigit()):
        err = ValueError()
        raise err
except ValueError as e:
    print("引發(fā)異常:",repr(e))
print('程序繼續(xù)執(zhí)行')

3.3航唆、raise傳遞異常

不帶任何參數(shù)的raise語句,可以再次引發(fā)剛剛發(fā)生過的異常牛曹,作用就是向外傳遞異常佛点。

print('程序開始執(zhí)行')
try:
    a = input('請輸入一個數(shù)字')
    #判斷用戶輸入的是否為數(shù)字
    if(not a.isdigit()):
        raise ValueError("輸入的必須是數(shù)字")
except ValueError as e:
    print("引發(fā)異常:",repr(e))
    raise
print('程序繼續(xù)執(zhí)行')
# ValueError: 輸入的必須是數(shù)字

4、assert語句

assert語句又稱作斷言,指的是期望用戶滿足指定的條件超营。
當(dāng)用戶定義的約束條件不滿足的時候鸳玩,它會觸發(fā)AssertionError異常,所以assert語句可以當(dāng)做條件式的raise語句演闭。
assert語句格式如下:
assert 邏輯表達(dá)式不跟,data
相當(dāng)于:
if not 邏輯表達(dá)式:
raise AssertionError(data)
assert后面緊跟一個邏輯表達(dá)式,相當(dāng)于條件米碰。Data通常是一個字符串窝革,當(dāng)條件為false時作為異常的描述信息。

print('程序開始執(zhí)行')
a = int(input('請輸入除數(shù)'))
assert a != 0,'除數(shù)不可以為0'
# AssertionError: 除數(shù)不可以為0

5吕座、自定義異常

python允許我們自定義異常虐译,只需要兩步:
1、創(chuàng)建一個繼承Exception類的子類吴趴,就是自定義異常類漆诽。
2、當(dāng)遇到自己設(shè)定的錯誤時锣枝,使用raise語句拋出自定義的異常厢拭。

#自定義異常類
class MyErr(Exception):
    def __init__(self,args):
        self.args = args
#觸發(fā)自定義異常
if __name__ == '__main__':
    print('程序開始執(zhí)行')
    try:
        raise MyErr('這是我自定義的異常')
    except MyErr as e:
        print('出現(xiàn)的異常為',e.args)

6、總結(jié)

這次主要針對Python的異常進(jìn)行介紹撇叁,包括異常類供鸠、拋出和捕捉系統(tǒng)內(nèi)置的異常、拋出和捕捉自定義異常陨闹,大家應(yīng)該深入了解了異常產(chǎn)生的原理楞捂,并知道如何在程序中運行它們。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末正林,一起剝皮案震驚了整個濱河市泡一,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觅廓,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涵但,死亡現(xiàn)場離奇詭異杈绸,居然都是意外死亡,警方通過查閱死者的電腦和手機矮瘟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門瞳脓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人澈侠,你說我怎么就攤上這事劫侧。” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵烧栋,是天一觀的道長写妥。 經(jīng)常有香客問我,道長审姓,這世上最難降的妖魔是什么珍特? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮魔吐,結(jié)果婚禮上扎筒,老公的妹妹穿的比我還像新娘。我一直安慰自己酬姆,他們只是感情好嗜桌,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辞色,像睡著了一般骨宠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淫僻,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天诱篷,我揣著相機與錄音,去河邊找鬼雳灵。 笑死棕所,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悯辙。 我是一名探鬼主播琳省,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躲撰!你這毒婦竟也來了针贬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拢蛋,失蹤者是張志新(化名)和其女友劉穎桦他,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谆棱,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡快压,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了垃瞧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔫劣。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖个从,靈堂內(nèi)的尸體忽然破棺而出脉幢,到底是詐尸還是另有隱情歪沃,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布嫌松,位于F島的核電站沪曙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏豆瘫。R本人自食惡果不足惜珊蟀,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望外驱。 院中可真熱鬧育灸,春花似錦、人聲如沸昵宇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓦哎。三九已至砸喻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒋譬,已是汗流浹背割岛。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犯助,地道東北人癣漆。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像剂买,于是被迫代替她去往敵國和親惠爽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

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