一顷蟀、Python3 錯(cuò)誤和異常
Python有兩種錯(cuò)誤很容易辨認(rèn):語(yǔ)法錯(cuò)誤和異常丐膝。
-
語(yǔ)法錯(cuò)誤
Python 的語(yǔ)法錯(cuò)誤或者稱(chēng)之為解析錯(cuò),是初學(xué)者經(jīng)常碰到的淫半,如下實(shí)例>
while True print('Hello world')
File "<stdin>", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
這個(gè)例子中溃槐,函數(shù) print() 被檢查到有錯(cuò)誤,是它前面缺少了一個(gè)冒號(hào)(:)科吭。
語(yǔ)法分析器指出了出錯(cuò)的一行昏滴,并且在最先找到的錯(cuò)誤的位置標(biāo)記了一個(gè)小小的箭頭。
-
異常
即便Python程序的語(yǔ)法是正確的对人,在運(yùn)行它的時(shí)候谣殊,也有可能發(fā)生錯(cuò)誤。運(yùn)行期檢測(cè)到的錯(cuò)誤被稱(chēng)為異常牺弄。大多數(shù)的異常都不會(huì)被程序處理姻几,都以錯(cuò)誤信息的形式展現(xiàn)在這里:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly
異常以不同的類(lèi)型出現(xiàn),這些類(lèi)型都作為信息的一部分打印出來(lái): 例子中的類(lèi)型有 ZeroDivisionError势告,NameError 和 TypeError蛇捌。
錯(cuò)誤信息的前面部分顯示了異常發(fā)生的上下文,并以調(diào)用棧的形式顯示具體信息咱台。
程序執(zhí)行過(guò)程中出現(xiàn)問(wèn)題導(dǎo)致程序無(wú)法執(zhí)行
-
異常的分類(lèi):
1络拌、程序遇到邏輯或算法錯(cuò)誤2、運(yùn)行過(guò)程中計(jì)算機(jī)錯(cuò)誤:內(nèi)存不夠或者io錯(cuò)誤
-
異常的步驟:
1回溺、異常產(chǎn)生盒音,檢查到錯(cuò)誤且解釋器認(rèn)為是異常,拋出異常2馅而、異常處理,異常處理譬圣,截獲異常瓮恭,系統(tǒng)忽略或者終止程序處理異常
image.pngimage.png
二、異常處理
-
1.異常處理的定義
python解釋器檢測(cè)到錯(cuò)誤湖笨,觸發(fā)異常(也允許程序員自己觸發(fā)異常)
程序員編寫(xiě)特定的代碼祷嘶,專(zhuān)門(mén)用來(lái)捕捉這個(gè)異常(這段代碼與程序邏輯無(wú)關(guān),與異常處理有關(guān))
如果捕捉成功則進(jìn)入另外一個(gè)處理分支愈诚,執(zhí)行你為其定制的邏輯登澜,使程序不會(huì)崩潰阔挠,這就是異常處理
-
2.異常處理的意義
python解析器去執(zhí)行程序,檢測(cè)到了一個(gè)錯(cuò)誤時(shí)脑蠕,觸發(fā)異常购撼,異常觸發(fā)后且沒(méi)被處理的情況下,程序就在當(dāng)前異常處終止谴仙,后面的代碼不會(huì)運(yùn)行迂求,所以你必須提供一種異常處理機(jī)制來(lái)增強(qiáng)你程序的健壯性與容錯(cuò)性
以下例子中,讓用戶(hù)輸入一個(gè)合法的整數(shù)晃跺,但是允許用戶(hù)中斷這個(gè)程序(使用 Control-C 或者操作系統(tǒng)提供的方法)揩局。用戶(hù)中斷的信息會(huì)引發(fā)一個(gè) KeyboardInterrupt 異常。
>>> while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again ")
try語(yǔ)句按照如下方式工作掀虎;
- 首先凌盯,執(zhí)行try子句(在關(guān)鍵字try和關(guān)鍵字except之間的語(yǔ)句)
- 如果沒(méi)有異常發(fā)生,忽略except子句烹玉,try子句執(zhí)行后結(jié)束驰怎。
- 如果在執(zhí)行try子句的過(guò)程中發(fā)生了異常,那么try子句余下的部分將被忽略春霍。如果異常的類(lèi)型和 except 之后的名稱(chēng)相符砸西,那么對(duì)應(yīng)的except子句將被執(zhí)行。最后執(zhí)行 try 語(yǔ)句之后的代碼址儒。
- 如果一個(gè)異常沒(méi)有與任何的except匹配芹枷,那么這個(gè)異常將會(huì)傳遞給上層的try中。
一個(gè) try 語(yǔ)句可能包含多個(gè)except子句莲趣,分別來(lái)處理不同的特定的異常鸳慈。最多只有一個(gè)分支會(huì)被執(zhí)行。
處理程序?qū)⒅会槍?duì)對(duì)應(yīng)的try子句中的異常進(jìn)行處理喧伞,而不是其他的 try 的處理程序中的異常走芋。
一個(gè)except子句可以同時(shí)處理多個(gè)異常,這些異常將被放在一個(gè)括號(hào)里成為一個(gè)元組潘鲫,例如:
except (RuntimeError, TypeError, NameError):
pass
最后一個(gè)except子句可以忽略異常的名稱(chēng)翁逞,它將被當(dāng)作通配符使用。你可以使用這種方法打印一個(gè)錯(cuò)誤信息溉仑,然后再次把異常拋出挖函。
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
try except 語(yǔ)句還有一個(gè)可選的else子句,如果使用這個(gè)子句浊竟,那么必須放在所有的except子句之后怨喘。這個(gè)子句將在try子句沒(méi)有發(fā)生任何異常的時(shí)候執(zhí)行津畸。例如:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
使用 else 子句比把所有的語(yǔ)句都放在 try 子句里面要好,這樣可以避免一些意想不到的必怜、而except又沒(méi)有捕獲的異常肉拓。
異常處理并不僅僅處理那些直接發(fā)生在try子句中的異常,而且還能處理子句中調(diào)用的函數(shù)(甚至間接調(diào)用的函數(shù))里拋出的異常梳庆。例如:
>>> def this_fails():
x = 1/0
>>> try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero
三暖途、常見(jiàn)的異常
- AttributeError 試圖訪問(wèn)一個(gè)對(duì)象沒(méi)有的屬性,比如foo.x靠益,但是foo沒(méi)有屬性x
- IOError 輸入/輸出異常丧肴;基本上是無(wú)法打開(kāi)文件
- ImportError 無(wú)法引入模塊或包;基本上是路徑問(wèn)題或名稱(chēng)錯(cuò)誤
- IndentationError 語(yǔ)法錯(cuò)誤(的子類(lèi)) 胧后;代碼沒(méi)有正確對(duì)齊
- IndexError 下標(biāo)索引超出序列邊界芋浮,比如當(dāng)x只有三個(gè)元素,卻試圖訪問(wèn)x[5]
- KeyError 試圖訪問(wèn)字典里不存在的鍵
- KeyboardInterrupt Ctrl+C被按下
- NameError 嘗試訪問(wèn)一個(gè)沒(méi)有申明的變量
- SyntaxError Python代碼非法壳快,代碼不能編譯(個(gè)人認(rèn)為這是語(yǔ)法錯(cuò)誤纸巷,寫(xiě)錯(cuò)了)
- TypeError 傳入對(duì)象類(lèi)型與要求的不符合
- UnboundLocalError 試圖訪問(wèn)一個(gè)還未被設(shè)置的局部變量,基本上是由于另有一個(gè)同名的全局變量眶痰,導(dǎo)致你以為正在訪問(wèn)它
- ValueError 傳入一個(gè)調(diào)用者不期望的值瘤旨,即使值的類(lèi)型是正確的
補(bǔ)充:
異常名稱(chēng) 描述
BaseException 所有異常的基類(lèi)
SystemExit 解釋器請(qǐng)求退出
KeyboardInterrupt 用戶(hù)中斷執(zhí)行(通常是輸入^C)
Exception 常規(guī)錯(cuò)誤的基類(lèi)
StopIteration 迭代器沒(méi)有更多的值
GeneratorExit 生成器(generator)發(fā)生異常來(lái)通知退出
StandardError 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類(lèi)
ArithmeticError 所有數(shù)值計(jì)算錯(cuò)誤的基類(lèi)
FloatingPointError 浮點(diǎn)計(jì)算錯(cuò)誤
OverflowError 數(shù)值運(yùn)算超出最大限制
ZeroDivisionError 除(或取模)零 (所有數(shù)據(jù)類(lèi)型)
AssertionError 斷言語(yǔ)句失敗
AttributeError 對(duì)象沒(méi)有這個(gè)屬性
EOFError 沒(méi)有內(nèi)建輸入,到達(dá)EOF 標(biāo)記
EnvironmentError 操作系統(tǒng)錯(cuò)誤的基類(lèi)
IOError 輸入/輸出操作失敗
OSError 操作系統(tǒng)錯(cuò)誤
WindowsError 系統(tǒng)調(diào)用失敗
ImportError 導(dǎo)入模塊/對(duì)象失敗
LookupError 無(wú)效數(shù)據(jù)查詢(xún)的基類(lèi)
IndexError 序列中沒(méi)有此索引(index)
KeyError 映射中沒(méi)有這個(gè)鍵
MemoryError 內(nèi)存溢出錯(cuò)誤(對(duì)于Python 解釋器不是致命的)
NameError 未聲明/初始化對(duì)象 (沒(méi)有屬性)
UnboundLocalError 訪問(wèn)未初始化的本地變量
ReferenceError 弱引用(Weak reference)試圖訪問(wèn)已經(jīng)垃圾回收了的對(duì)象
RuntimeError 一般的運(yùn)行時(shí)錯(cuò)誤
NotImplementedError 尚未實(shí)現(xiàn)的方法
SyntaxError Python 語(yǔ)法錯(cuò)誤
IndentationError 縮進(jìn)錯(cuò)誤
TabError Tab 和空格混用
SystemError 一般的解釋器系統(tǒng)錯(cuò)誤
TypeError 對(duì)類(lèi)型無(wú)效的操作
ValueError 傳入無(wú)效的參數(shù)
UnicodeError Unicode 相關(guān)的錯(cuò)誤
UnicodeDecodeError Unicode 解碼時(shí)的錯(cuò)誤
UnicodeEncodeError Unicode 編碼時(shí)錯(cuò)誤
UnicodeTranslateError Unicode 轉(zhuǎn)換時(shí)錯(cuò)誤
Warning 警告的基類(lèi)
DeprecationWarning 關(guān)于被棄用的特征的警告
FutureWarning 關(guān)于構(gòu)造將來(lái)語(yǔ)義會(huì)有改變的警告
OverflowWarning 舊的關(guān)于自動(dòng)提升為長(zhǎng)整型(long)的警告
PendingDeprecationWarning 關(guān)于特性將會(huì)被廢棄的警告
RuntimeWarning 可疑的運(yùn)行時(shí)行為(runtime behavior)的警告
SyntaxWarning 可疑的語(yǔ)法的警告
UserWarning 用戶(hù)代碼生成的警告</pre>