摘要:在前面介紹語法的過程中,我們已經(jīng)接觸到了解釋器給的錯(cuò)誤和異常,但并沒有詳細(xì)講解它們。解釋器這樣報(bào)出的好處是告訴我們哪一行代碼出錯(cuò)了錯(cuò)誤的類型是什么。
在前面介紹Python語法的過程中,我們已經(jīng)接觸到了解釋器給的錯(cuò)誤和異常,但并沒有詳細(xì)講解它們?,F(xiàn)在我們就全面的來學(xué)習(xí)Python是對(duì)語法錯(cuò)誤等錯(cuò)誤進(jìn)行定義和處理的,這包括至少有兩種可以區(qū)分的錯(cuò)誤,它們是語法錯(cuò)誤和異常。
語法錯(cuò)誤Python的語法錯(cuò)誤就是不符合Python語法的錯(cuò)誤,又稱為解析錯(cuò)誤。這種錯(cuò)誤是初學(xué)Python對(duì)語法不是很熟悉時(shí)經(jīng)常犯的。比如下面的例子:
In [1]: if 2 == 3 print("imposible") File "", line 1 if 2 == 3 print("imposible") ^ SyntaxError: invalid syntax
解釋器在解釋上面的代碼時(shí),就會(huì)發(fā)現(xiàn)表達(dá)式2 == 3后面少了一個(gè)冒號(hào):,這時(shí)它就會(huì)報(bào)出一個(gè)錯(cuò)誤SyntaxError: invalid syntax,并且輸出出現(xiàn)語法錯(cuò)誤的那一行,并顯示一個(gè)“箭頭”,指向這行里面檢測(cè)到第一個(gè)錯(cuò)誤。 錯(cuò)誤是由箭頭指示的位置上面的 token 引起的(或者至少是在這里被檢測(cè)出的)。文件名和行號(hào)也會(huì)被輸出,以便輸入來自腳本文件時(shí)你能知道去哪檢查。
解釋器這樣報(bào)出的好處是:
(1)告訴我們哪一行代碼出錯(cuò)了;
(2)錯(cuò)誤的類型是什么。
這樣非常有利于我們排除錯(cuò)誤,修正程序。
異常(Exception)如果我們對(duì)語法很熟悉,寫出來的代碼在語法上都是正確的,但也不能保證在執(zhí)行時(shí)程序不會(huì)引發(fā)錯(cuò)誤。在執(zhí)行時(shí)檢測(cè)到的錯(cuò)誤被稱為異常,異常不一定會(huì)導(dǎo)致嚴(yán)重后果,但我們不在代碼中對(duì)它們進(jìn)行處理,就可能會(huì)導(dǎo)致程序中斷執(zhí)行。下面是一些常見的錯(cuò)誤異常信息:
In [2]: 5 / 0 ---------------------------- ZeroDivisionError Traceback (most recent call last)in ----> 1 5 / 0 ZeroDivisionError: division by zero In [3]: a + 3 ------------------------------ NameError Traceback (most recent call last) in ----> 1 a + 3 NameError: name "a" is not defined In [4]: 10 + "1" -------------------------------- TypeError Traceback (most recent call last) in ----> 1 10 + "1" TypeError: unsupported operand type(s) for +: "int" and "str"
我們看到,異常有不同的類型,其類型名稱會(huì)作為錯(cuò)誤信息的一部分中打印出來,上述示例中的異常類型分別是:ZeroDivisionError,NameError和TypeError。對(duì)于所有內(nèi)置異常,打印出來的字符串是內(nèi)置異常的名稱。對(duì)于用戶定義的異常則不一定如此,但我們自定義異常時(shí)最好按照內(nèi)置異常那樣去定義,這是一個(gè)很有用的規(guī)范。標(biāo)準(zhǔn)的異常類型是內(nèi)置的標(biāo)識(shí)符,而不是保留關(guān)鍵字。
打印出來的異常名稱后面是異常發(fā)生的原因。錯(cuò)誤信息的前一部分以堆?;厮莸男问斤@示發(fā)生異常時(shí)代碼的上下文。一般它包含列出源代碼行的堆?;厮荩坏撬粫?huì)顯示從標(biāo)準(zhǔn)輸入中讀取的行。
Python內(nèi)置了很多異常,它們都從BaseException繼承而來,下面是內(nèi)置異常的繼承關(guān)系:
異常處理既然程序會(huì)拋出異常,那我們就可以編寫代碼處理這些異常。先看下面的例子,它會(huì)讓用戶一直輸入,直到輸入的是一個(gè)有效的整數(shù)。我們也可以使用Control-C來中斷程序;這個(gè)Control-C引起的中斷會(huì)引發(fā) KeyboardInterrupt 異常。
In [6]: while 1: ...: try: ...: n = int(input("input a number:")) ...: print("You typed number:", n) ...: break ...: except ValueError: ...: print("Nooo! It is not a number, Try agin") ...: input a number:a Nooo! It is not a number, Try agin input a number:b Nooo! It is not a number, Try agin input a number:3 You typed number: 3
當(dāng)我們輸入a時(shí),它不能轉(zhuǎn)換成整數(shù)就會(huì)報(bào)錯(cuò)異常ValueError。轉(zhuǎn)換為整數(shù)的那條語句報(bào)出了異常,它后面的語句就不再執(zhí)行,而是跳到except那里去執(zhí)行它里面的語句。
try語句的工作原理如下:
首先,執(zhí)行try 子句,即try和except關(guān)鍵詞之間的(一行或多行)語句;
如果沒有發(fā)生異常,則跳過except子句并完成try子句的執(zhí)行;
如果執(zhí)行try子句是發(fā)生了異常,則跳過該子句的剩下部分。然后,去匹配異常的類型和except關(guān)鍵字后面的異常,如果異常類型匹配則執(zhí)行except子句,之后繼續(xù)執(zhí)行try語句后面的代碼。
如果發(fā)生的異常和except后面的異常不匹配,則將其傳遞到外部的try語句,如果沒有找到處理代碼,則它是一個(gè)未處理異常,執(zhí)行將停止并顯示錯(cuò)誤信息。
一個(gè)try語句可以有多個(gè)except子句,以便不同的異常用不同的處理程序進(jìn)行處理。每次遇到異常最多會(huì)執(zhí)行一個(gè)except子句,也就是說,處理程序只處理相應(yīng)的異常,而不處理同一try語句內(nèi)其它處理程序的異常。但是,一個(gè)except子句可以將多個(gè)異常包含在一個(gè)元組內(nèi),例如:
try: ... except (RuntimeError, TypeError, NameError): pass
異常都是繼承于BaseException,如果except子句中的類和發(fā)生的異常是同一個(gè)類,或者是異常的基類(父類),則異常和except子句中的類是兼容的。但是,反過來則不成立。我們看看下面的代碼,它將一次打印B,C,D。
class B(Exception): pass class C(B): pass class D(C): pass for cls in [B, C, D]: try: raise cls() except D: print("D") except C: print("C") except B: print("B")
如果我把 except 子句顛倒過來,把 except B 放到第一個(gè),猜猜它將會(huì)打印出什么?答案是它將打印 B,B,B。也就是第一個(gè)匹配的 except 子句被觸發(fā),因?yàn)锽是C、D的父類。
最后的 except 子句可以省略異常名稱,以用作通配符匹配所有的異常。這個(gè)要小心使用,因?yàn)檫@種方式很容易掩蓋真正的編程錯(cuò)誤!但是它可用于打印錯(cuò)誤消息,然后重新引發(fā)異常(同樣允許調(diào)用者處理異常):
import sys try: f = open("zzz.txt") s = f.readline() i = int(s.strip()) except OSError as err: print("OS error: {0}".format(err)) except ValueError: print("Could not convert string to integer.") except: print("Unexpected error:", sys.exc_info()[0]) raise
try 語句有一個(gè)可選的 else 子句,在使用時(shí)它必須放在所有的 except 子句后面。對(duì)于在try 子句不引發(fā)異常時(shí)必須執(zhí)行的代碼來說很有用。例如:
try: f = open("zzz.txt", "r") except OSError: print("cannot open", "zzz.txt") else: print("zzz.txt", "has", len(f.readlines()), "lines") f.close()
使用else子句的好處是,它避免了意外捕獲由else子句引發(fā)的異常。也就是說,程序中我們只想捕獲open引發(fā)的異常,而不捕獲f.readlines()引發(fā)的錯(cuò)誤。
異常在拋出時(shí)可能具有關(guān)聯(lián)的值,稱為異常參數(shù)。參數(shù)的存在和類型取決于異常類型。
except子句可以在異常名稱后面指定一個(gè)變量,這個(gè)變量就是該異常的實(shí)例,它的參數(shù)存儲(chǔ)在instance.args中。為了方便起見,異常實(shí)例定義了__str__(),因此可以直接打印參數(shù)而無需引用.args。也可以在拋出之前首先實(shí)例化異常,并根據(jù)需要向其添加任何屬性。:
In [7]: try: ...: raise Exception("認(rèn)真學(xué)", "Python") ...: except Exception as e: ...: print(type(e)) ...: print(e.args) ...: print(e) ...: a, b = e.args ...: print("a =", a) ...: print("b =", b) ...:("認(rèn)真學(xué)", "Python") ("認(rèn)真學(xué)", "Python") a = 認(rèn)真學(xué) b = Python
異常處理程序不僅可以處理try子句中遇到的異常,還可以處理try子句中調(diào)用的函數(shù)的內(nèi)部發(fā)生的異常,例如:
In [8]: def func(): ...: return 10/0 ...: In [9]: try: ...: func() ...: except ZeroDivisionError as err: ...: print("run-time error:", err) ...: run-time error: division by zero
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/43850.html
摘要:語句就是幫助我們拋出知道異常的,比如的使用很簡(jiǎn)單,它的語法如下如果它后面不帶表達(dá)式參數(shù),它會(huì)重新引發(fā)當(dāng)前作用域內(nèi)最后一個(gè)激活的異常。,用于異常的串聯(lián)。自定義的異常類的名稱通常以錯(cuò)誤結(jié)尾,類似與內(nèi)置標(biāo)準(zhǔn)異常的命名。 前面我們講到的Python編程過程中,在可能出現(xiàn)異常的地方使用嘗試語句,來正確的處理一些異常,可以保證程序不中斷繼續(xù)運(yùn)行。 showImg(https://segmentfa...
摘要:新的稱為子類,而被繼承的稱為基類父類或超類。繼承最大的好處是子類獲得了父類的全部功能。在繼承關(guān)系中,如果一個(gè)實(shí)例的數(shù)據(jù)類型是某個(gè)子類,那它的數(shù)據(jù)類型也可以被看做是父類。 在上一篇中我們介紹了模塊和數(shù)據(jù)結(jié)構(gòu),這一篇將介紹面向?qū)ο缶幊獭? 面向?qū)ο缶幊?面向?qū)ο缶幊獭狾bject Oriented Programming,簡(jiǎn)稱 OOP,是一種程序設(shè)計(jì)思想。OOP 把對(duì)象作為程序的基本單元...
?前言 代碼出現(xiàn)異常而報(bào)錯(cuò)再正常不過了,但為什么要處理異常? 由于異常的存在,代碼運(yùn)行時(shí)會(huì)出現(xiàn)一大堆的紅色字體提示,對(duì)于程序員還好,見紅色報(bào)錯(cuò)見多了習(xí)慣了,但如果你開發(fā)出來的東西要給別人看,那么不懂代碼的人就會(huì)一臉懵逼,對(duì)產(chǎn)品的印象都不太好了。 比如我們經(jīng)常簡(jiǎn)單網(wǎng)頁丟失的情況,其實(shí)是就是網(wǎng)頁代碼執(zhí)行時(shí)發(fā)生了異常,但有的網(wǎng)頁還是很個(gè)性的,提示的信息可能是比較人性化的,比如CSDN你收藏的文章被后臺(tái)刪...
摘要:本文與大家分享一些編程語言的入門書籍,其中不乏經(jīng)典。全書貫穿的主體是如何思考設(shè)計(jì)開發(fā)的方法,而具體的編程語言,只是提供一個(gè)具體場(chǎng)景方便介紹的媒介。入門入門容易理解而且讀起來幽默風(fēng)趣,對(duì)于編程初學(xué)者和語言新手而言是理想的書籍。 本文與大家分享一些Python編程語言的入門書籍,其中不乏經(jīng)典。我在這里分享的,大部分是這些書的英文版,如果有中文版的我也加上了。有關(guān)書籍的介紹,大部分截取自是官...
閱讀 3482·2023-04-25 14:07
閱讀 3638·2021-09-28 09:35
閱讀 2160·2019-08-30 15:55
閱讀 1480·2019-08-30 13:48
閱讀 2562·2019-08-30 13:16
閱讀 3288·2019-08-30 12:54
閱讀 3298·2019-08-30 11:19
閱讀 1948·2019-08-29 17:17