国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

2015/9/10Python基礎(11):錯誤和異常

2019-11-14 17:01:11
字體:
來源:轉載
供稿:網友

程序在執行的過程中會產生異常,出現錯誤在以前的一個時期是致命的,后來隨著程序的發展,使得一些錯誤的處理方式是柔和的,發生錯誤會產生一些錯誤的診斷信息和一些模糊的提示。幫助我們來處理異常。
今天將學習Python的異常。

程序會有語法或者邏輯上的錯誤,語法的錯誤會導致解釋器或編譯器無法工作,那么程序并U幣能執行。
而語法正確的情況下,只有邏輯的問題。邏輯的問題分為兩種情況,一個是由于不完整或者不合法的輸入所致。另一個是邏輯無法生成,計算或者執行,這些錯誤也叫域錯誤和范圍錯誤。
Python檢測到錯誤時,就出現了異常。

異常是因為程序出現了錯誤而在正常控制論外采取的行為。這個行為有兩個階段:
1、異常引發的錯誤階段
2、檢測(和采取可能的措施)階段
第一個階段是檢測到錯誤并意識到異常條件,然后解釋器會引發一個異常,打斷當前流。當然Python允許程序員自己引發異常。
第二階段是處理異常,有忽略錯誤(記錄錯誤但不采取措施,采取補救措施后終止程序),或是減輕問題的影響后設法繼續執行程序。
類似Python這樣支持引發和處理異常的語言,可以讓開發人員在錯誤發生時更直接地控制它們。這樣會使程序的健壯性大大提高。

Python中有的異常
每次當程序崩潰或者因錯誤終止時,會看到"trackback/跟蹤返回"消息,有解釋器提供的信息,包括錯誤的名稱,原因,以及發生錯誤的行號。
有以下的異常例子:

NameError: 嘗試訪問一個未申明的變量>>> fooTraceback (innermost last): File "<stdin>", line 1, in ?NameError: name 'foo' is not defined

這是訪問了沒有初始化的變量。訪問變量將由解釋器進行搜索,如果請求的名字沒有在任何名稱空間里找到,就會生成一個NameError異常。

ZeroDivisionError: 除數為零>>> 1/0Traceback (innermost last): File "<stdin>", line 1, in ?ZeroDivisionError: integer division or modulo by zero

任何數值被零除都會引發ZeroDivisionError異常

SyntaxError: Python 解釋器語法錯誤>>> forFile "<string>", line 1for^SyntaxError: invalid syntax

SyntaxError異常是唯一一個不再運行時發生的異常。在改正它之前程序無法執行。

IndexError:請求的索引超出序列范圍>>> aList = []>>> aList[0]Traceback (innermost last): File "<stdin>", line 1, in ?IndexError: list index out of range

IndexError 在你嘗試使用一個超出范圍的值索引序列時引發.

KeyError:請求一個不存在的字典關鍵字>>> aDict = {'host': 'earth', 'port': 80}>>> PRint aDict['server'] Traceback (innermost last):File "<stdin>", line 1, in ? KeyError: server

使用錯誤的鍵請求字典就會引發一個KeyError異常。

IOError: 輸入/輸出錯誤>>> f = open("blah") Traceback (innermost last):File "<stdin>", line 1, in ?IOError: [Errno 2] No such file or directory: 'blah'

類似嘗試打開一個不存在的磁盤文件一類的操作會引發一個操作系統輸入/輸出(I/O)錯誤. 任何類型的 I/O 錯誤都會引發 IOError 異常.

AttributeError: 嘗試訪問未知的對象屬性>>> class myClass(object):... pass...>>> myInst = myClass()>>> myInst.bar = 'spam'>>> myInst.bar'spam'>>> myInst.fooTraceback (innermost last): File "<stdin>", line 1, in ?AttributeError: foo

在 myInst.bar 儲存了一個值, 也就是實例 myInst 的 bar 屬性. 屬性被定義后, 我們可以使用熟悉的點/屬性操作符訪問它, 但如果是沒有定義屬性, 例如我們訪問foo 屬性, 將導致一個 AttributeError 異常.

檢測和處理異常
Python的異常檢測處理有專門的語法
異常通過try語句來檢測,任何在try語句塊里的代碼都會被檢測,檢查有無異常發生。
try語句主要有兩種主要形式:try-except 和 try-finally.這兩種語句互斥,只能使用其中一種。一個try語句對應一個或多個 except 子句,但只能對應一個 finally 子句, 或是一個 try-except-finally 復合語句。
try-except語句檢測和處理異常,可以添加一個可選的 else 子句處理沒有探測到異常時執行的代碼。而 try-finally 只允許檢測異常并做一些必要的清楚工作,沒有任何異常處理措施。復合語句可以做這兩者做到。

try-except語句語法如下:

try:  try_suite # 監控這里的異常except Exception[, reason]:  except_suite # 異常處理代碼

一下是一個例子:

>>> try:  f = open('try', 'r')except IOError, e:  print 'could not open file:', ecould not open file: [Errno 2] No such file or directory: 'try'

在這個例子里,我們只捕捉 IOError 異常,任何其他異常都不會被處理器捕獲。

核心筆記:忽略代碼,繼續執行,向上移交
try 語句塊中異常發生點后的剩余語句永遠不會到達,一旦一個異常被引發,就必須決定控制流下一步到達的位置。剩余代碼將被忽略,解釋器將搜索處理器,一旦找到,就開始執行處理器中的代碼。
如果沒有找到合適的處理器,那么異常就向上移交給調用者去處理,這意味著堆棧框架立即回到之前的那個。如果在上層調用者也沒有找到對應處理器,該異常會繼續被向上移交,直到找到合適的處理器,如果到達最頂層仍然沒有找到對應處理器,那么就認為這個異常是未處理的,Python解釋器會顯示出跟蹤返回消息,然后退出。

安全地調用內建函數
在下例中,我們將看到當給float()錯誤的值后會得到的錯誤,然后用try-except封裝一個安全的函數:

>>> float('abc')Traceback (most recent call last):File "<pyshell#5>", line 1, in <module>float('abc')ValueError: could not convert string to float: abc>>> float(['this is', 1, 'list'])Traceback (most recent call last):File "<pyshell#6>", line 1, in <module>float(['this is', 1, 'list'])TypeError: float() argument must be a string or a number>>> def safe_float(obj):  try:    retval = float(obj)  except ValueError:    retval = 'could not convert non-number to float'  except TypeError:    retval = 'object type cannot be converted to float'  return retval>>> safe_float('xyz')'could not convert non-number to float'>>> safe_float(['this is', 1, 'list'])'object type cannot be converted to float'
這里使用了多個except子句的處理,語法如下:
except Exception1[, reason1]:  suite_for_exception_Exception1except Exception2[, reason2]:  suite_for_exception_Exception2 ...

 

 

還可以在一個except子句里處理多個異常,這種處理是要求異常被放在一個元組里:

except (Exception1, Exception2)[, reason]:  suite_for_Exception1_and_Exception2

用這種方法改變上面的函數,可以寫成這樣:

def safe_float(obj):  try:    retval = float(obj)  except (ValueError, TypeError):    retval = 'argument must be a number or numeric string'  return retval

except語句可以處理任意多個異常,前提是放在一個元組,如下:

except (Exc1,...ExcN)[, reason]:  suite_for_exceptions_Exc1_to_ExcN

而但我們想捕獲所有的異常呢?
可以如下來寫:

try:  ...except Exception, e:  ...# 發生了異常,異常種類存儲在e里

另一個不太推薦的方法是用裸 except 子句:

try:  ...except:  ...

下面這種裸 except 子句的方法雖然捕獲大多異常,但你并不會知道導致異常的主要原因。所以沒辦法學會避免,故而不推薦這種方法。也許以后會取消這種方法的支持
關于捕獲所有異常,有些異常不是由錯誤條件引起。他們是 SystemExit 和 KeyboardInterrupt.
SystemExit 是由于當前 Python 應用程序需要退出, KeyboardInterupt 代表用戶按下了 CTRL—C(^C),想要關閉 Python。在真正需要時,這些異常會被異常處理捕獲。
在Python2.5以后,異常發生了遷移,啟用了一個BaseException作為所有異常的母親,KeyboardInterrupt 和 SystemExit 從 Exception 里移出,和 Exception 平級:

-BaseException
  |- KeyboardException
  |- SystemExit
  |- Exception
  |- (all other current built-in exceptions)

 

核心風格: 不要處理并忽略所有的錯誤
Python提供 try—except 語句是為了更好地跟蹤潛在的錯誤并在代碼里準備好處理異常的邏輯。它的母的是為了減少程序出錯的次數并在出錯后仍能保證程序正常運行。
如果我們一直用一個通用的except過濾了任何致命的錯誤,忽略它們。比如說使用裸 except 語句。
我們知道錯誤無法避免,try—except的作用是提供一個可以提示錯誤或者處理錯誤的機制,而不是錯誤過濾器,過濾任何致命的錯誤是沒有意義的。

異常參數
異常也可以有參數,異常引發后它會被傳遞給異常處理器。當異常被引發后參數是作為附加幫助信息傳遞給異常處理器的。雖然異常原因是可選的,但標準內建異常提供至少一個參數,指示異常原因的一個字符串。
異常的參數需要一個變量來保存,放在 except 后接在要處理的異常后面。也就是上面那個例子里我使用的e變量
單個異常的語句里:

except Exception[, reason]:  suite_for_Exception_with_Argumentexcept (Exception1, Exception2, ..., ExceptionN)[, reason]:  suite_for_Exception1_to_ExceptionN_with_Argument

這個reason將會是一個包含來自導致異常的代碼的診斷信息的類實例。異常參數自身會組成一個元組,并存儲為類實例的屬性。上面這樣的用法,reason將會是Exception類的實例。
大部分的內建異常都是從StandardError派生的異常,這個元組只包含一個指示錯誤原因的字符串,一般來說,名字就是一個滿意的線索了。
而某些第三方或是其他外部庫并不遵循這個標準協議。

核心風格: 遵循異常參數規范
在自己的代碼里引發內建(built-in)的異常時,盡量遵循規范,用和已有Python代碼一致信息作為傳遞給異常的參數元組的一部分。這樣可以保證代碼一致性,同時也能避免其他應用程序在使用你的模塊時發生錯誤。

同時try-except語句還可以加上else語句
和正常的執行沒有什么不同,也就是在try范圍中沒有異常被檢測到時,執行else子句。

finally子句
finally子句是無論異常是否發生,是否捕捉都會的執行一段代碼。

try—finally
語法如下:

try:    try_suitefinally:    finally_suite

當 try 范圍中產生一個異常時,會立即跳轉到finally語句段,當finally中所有代碼執行完畢后,會繼續向上一層引發異常。

同樣的,我們還有try-except-else-finally語句,可以使用整個過程

 

上下文管理
with語句
with也是用于簡化代碼的,隱藏了底層的應用。try-except 和 try-finally的一種特定的配合用法是保證共享資源的唯一分配,并在任務結束時釋放它,比如文件,線程資源,簡單同步,數據庫連接等等,with語句的目標就是應用在這種場景。
with語句的目的在于從流程圖中把 try,except 和finally 關鍵字和資源分配釋放相關代碼統統去掉,而不是像 try-except-finally那樣僅僅簡化代碼使之易用。with語法基本用法如下:
with context_expr [as var]:
with_suite
這看起來很簡單,但是其背后還有一些工作要做。這并不如看上去的那么容易,因為不能對 Python 的任意符號使用 with 語句。它僅能工作于支持上下文管理協議的對象。
支持該協議的對象暫時有如下:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BounderSemaphore
以file舉例

with open(r'/file.txt','r') as f:for eachLine in f:  # ...do stuff with eachLine or f...

這段代碼會完成準備工作,比如試圖打開一個文件,如果一切正常,把文件對象賦值給 f.然后用迭代器遍歷文件中的每一行,當完成時,關閉文件。無論在這一段代碼的開始,中間,還是結束是發生異常,會執行清理的代碼,此外文件仍會被自動的關閉。

觸發異常
除了解釋器引發的異常,程序員編寫API時也希望在遇到錯誤的輸入時觸發異常,為此,Python提供了一種機制讓程序員明確的觸發異常,就是raise語句。
raise的一般用法是:

raise [SomeException [, arges [, trackback]]]

第一個參數,SomeException,是觸發異常的名字。如果有,它必須是一個字符串,類或實例.如果有其他參數(arg 或 traceback)就必須提供SomeException.
第二個符號為可選的 args ,來傳給異常。這可以是一個單獨的對象也可以是一個對象的元組。如果args原本就是元組,那么就將其傳給異常區處理;如果args是一個單獨的對象,就生成只有一個元素的元組。大多數情況下,單一的字符串用來指示錯誤的原因。如果傳的是元組,通常的組成是一個錯誤字符串,一個錯誤編號,可能還有一個錯誤的地址,比如文件。
最后一個參數,traceback,也是可選的。如果有的話,是新生成的一個用于異常-正常話的追蹤對象。當你想重新引發異常時,第三個參數很有用。

斷言
斷言是一句必須等價于布爾真的判定;此外發生發生異常也意味著表達式為假。
斷言語句語法:

assert expression[, arguments]

斷言成功不采取任何措施,否則處罰AssertionError異常。


為什么用異常?
毫無疑問,只要軟件存在,錯誤就會一直存愛。區別在于當今快節奏的計算世界,我們的執行環境已經改變,所以需要改變錯誤處理,以準確反映軟件的開發環境。
在互聯網和網上電子商業應用越來越普及的過程中,web服務器將是應用軟件的主要客戶,意味著應用程序再也不能只是直接失敗或崩潰,否則會導致瀏覽器的錯誤。
而一些用戶輸入的數據無效的錯誤,必須轉化成一個非錯誤,所以運行環境必須夠強健。我們不能僅僅返回這是一個錯誤的信息。而應該返回足夠多的信息,確保用戶平滑地學到使用經驗。
即使面對一個錯誤,應用應該成功的中止,不至于災難性地影響執行環境。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 招远市| 叙永县| 邻水| 鄢陵县| 石渠县| 毕节市| 凤城市| 黔江区| 南靖县| 龙游县| 翼城县| 新化县| 宜川县| 伊宁市| 阿巴嘎旗| 江西省| 格尔木市| 万全县| 涞源县| 武乡县| 嘉黎县| 武宣县| 商城县| 济源市| 那曲县| 和平区| 株洲市| 交城县| 梁山县| 阿图什市| 明水县| 江北区| 东阿县| 广德县| 开封市| 古浪县| 宁陵县| 米易县| 临泉县| 三门峡市| 镇雄县|