日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第八章 异常

發(fā)布時間:2023/12/1 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第八章 异常 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第八章 異常

異常事件可能是錯誤(如試圖除以零),也可能是通常不會發(fā)生的事情。
Python提供功能強大的替代解決方案——異常處理機制。

異常是什么?

Python使用異常對象來表示異常狀態(tài),并在遇到錯誤時引發(fā)異常。異常對象未被處理或捕 獲)時,程序將終止并顯示一條錯誤消息(traceback)。

1 / 0 ''' ZeroDivisionError Traceback (most recent call last) <ipython-input-146-05c9758a9c21> in <module>() ----> 1/0 ZeroDivisionError: division by zero '''

事實上,每個異常都是某個類(這里是ZeroDivisionError)的實例.

讓事情沿你指定的軌道出錯

raise 語句

要引發(fā)異常,可使用raise語句,并將一個類(必須是Exception的子類)或實例作為參數(shù)。將類作為參數(shù)時,將自動創(chuàng)建一個實例。

在第一個示例(raise Exception)中,引發(fā)的是通用異常,沒有指出出現(xiàn)了什么錯誤。
在第二個示例中,添加了錯誤消息beyondhuangjiaju。

raise Exception ''' Exception Traceback (most recent call last) <ipython-input-147-fca2ab0ca76b> in <module>() ----> raise ExceptionException: ''' raise Exception('beyondhuangjiaju') ''' Exception Traceback (most recent call last) <ipython-input-149-dfdac40c1137> in <module>() ----> raise Exception('beyondhuangjiaju')Exception: beyondhuangjiaju '''raise ArithmeticError ''' ArithmeticError Traceback (most recent call last) <ipython-input-150-36d9a98b39c2> in <module>() ----> raise ArithmeticErrorArithmeticError: ''' raise ArithmeticError("beyondhuangjiaju") ''' ArithmeticError Traceback (most recent call last) <ipython-input-151-a6ed875c1de3> in <module>() ----> 1 raise ArithmeticError("beyondhuangjiaju")ArithmeticError: beyondhuangjiaju '''

一些內置的異常類如下表所示:

類名描述
Exception幾乎所有的異常類都是從它派生而來的
AttributeError引用屬性或給它賦值失敗時引發(fā)
OSError操作系統(tǒng)不能執(zhí)行指定的任務(如打開文件)時引發(fā),有多個子類
IndexError使用序列中不存在的索引時引發(fā),為LookupError的子類
KeyError使用映射中不存在的鍵時引發(fā),為LookupError的子類
NameError找不到名稱(變量)時引發(fā)
SyntaxError代碼不正確時引發(fā)
TypeError將內置操作或函數(shù)用于類型不正確的對象時引發(fā)
ValueError將內置操作或函數(shù)用于這樣的對象時引發(fā):其類型正確但包含的值不合適
ZeroDivisionError在除法或求模運算的第二個參數(shù)為零時引發(fā)

自定義的異常類

如何創(chuàng)建異常類呢?
就像創(chuàng)建其他類一樣,但務必直接或間接地繼承Exception(這意味著從任何內置異常類派生都可以)。
當然,如果你愿意,也可在自定義異常類中添加方法。

class SomeCustomBeyondException(Exception): pass

捕獲異常

異常比較有趣的地方是可對其進行處理,通常稱之為捕獲異常。
可使用try/except語句。

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except ZeroDivisionError: print("The second number can't be zero!")''' Enter the first number: 5 Enter the second number: 0 The second number can't be zero! '''

不用提供參數(shù)

來看一個能夠“抑制”異常ZeroDivisionError的計算器類。如果啟用了這種功能,計算器將打印一條錯誤消息,而不讓異常繼續(xù)傳播。在與用戶交互的會話中使用這個計算器時,抑制異常很有用;但在程序內部使用時,引發(fā)異常是更佳的選擇(此時應關閉“抑制”功能)。

class MuffledCalculator: muffled = False def calc(self, expr): try: return eval(expr) except ZeroDivisionError: if self.muffled: print('Division by zero is illegal') else: raisecalculator = MuffledCalculator() calculator.calc('10 / 2')#結果為:5.0 calculator.calc('10 / 0')#報錯!!!calculator.muffled = True calculator.calc('10 / 0') #結果為:Division by zero is illegal

如果無法處理異常,在except子句中使用不帶參數(shù)的raise通常是不錯的選擇,但有時你可能想引發(fā)別的異常。
在這種情況下,導致進入except子句的異常將被作為異常上下文存儲起來,并出現(xiàn)在最終的錯誤消息中。

try:1/0 except ZeroDivisionError:raise ValueError #在處理上述異常時,引發(fā)了另一個異常:''' ZeroDivisionError Traceback (most recent call last) <ipython-input-160-14da06562399> in <module>()1 try: ----> 2 1/03 except ZeroDivisionError:ZeroDivisionError: division by zeroDuring handling of the above exception, another exception occurred:ValueError Traceback (most recent call last) <ipython-input-160-14da06562399> in <module>()2 1/03 except ZeroDivisionError: ----> 4 raise ValueErrorValueError: '''#可使用raise ... from ...語句來提供自己的異常上下文,也可使用None來禁用上下文。 try:1/0 except ZeroDivisionError:raise ValueError from None''' ValueError Traceback (most recent call last) <ipython-input-161-f4775ad0e53d> in <module>()2 1/03 except ZeroDivisionError: ----> 4 raise ValueError from NoneValueError: '''

多個 except 子句

當你在輸入字符串的時候,此時會引發(fā)另一種異常,該程序中的except子句只捕獲ZeroDivisionError異常,這種異常將成為漏網(wǎng)之魚,導致程序終止。

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except ZeroDivisionError: print("The second number can't be zero!")''' Enter the first number: 1999 Enter the second number: beyond --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-2-f93dbf72378b> in <module>()1 try:2 x = int(input('Enter the first number: ')) ----> 3 y = int(input('Enter the second number: '))4 print(x / y)5 except ZeroDivisionError:ValueError: invalid literal for int() with base 10: 'beyond' '''

為同時捕獲這種異常,可在try/except語句中再添加一個except子句。

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except ZeroDivisionError: print("The second number can't be zero!") except TypeError:print("That wasn't a number,was it?")

一箭雙雕

如果要使用一個except子句捕獲多種異常,可在一個元組中指定這些異常。
在except子句中,異常兩邊的圓括號很重要。

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except (ZeroDivisionError,TypeError,NameError): print("Your numbers were bogus ...")

在上述代碼中,如果用戶輸入字符串、其他非數(shù)字值或輸入的第二個數(shù)為零,都將打印同樣的錯誤消息。當然,僅僅打印錯誤消息幫助不大。

捕獲對象

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except (ZeroDivisionError,TypeError) as e: print(e)

這里的except子句捕獲兩種異常,但由于同時顯式地捕獲了對象本身,因此可將其打印出來,讓用戶知道發(fā)生了什么情況。

一網(wǎng)打盡

即使程序處理了好幾種異常,還是可能有一些漏網(wǎng)之魚。
如果用戶在提示時不輸入任何內容就按回車鍵,將出現(xiàn)一條錯誤消息,這種異常未被try/except語句捕獲,這理所當然,因為你沒有預測到這種問題,也沒有采取相應的措施。

try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except: print("Something wrong happened...")''' Enter the first number: Something wrong happened... '''

像這樣捕獲所有的異常很危險,因為這不僅會隱藏你有心理準備的錯誤,還會隱藏你沒有考慮過的錯誤。
在大多數(shù)情況下,更好的選擇是使用except Exception as e并對異常對象進行檢查。
SystemExitKeyboardInterrupt從**BaseException(Exception的超類)**派生而來

萬事大吉

使用except Exception as e的小技巧在這個小型除法程序中打印更有用的錯誤消息。

while True:try:x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) value = x / yprint("x / y is",value)except Exception as e:print("Invalid input:",e)print('Please try again')else:break''' Enter the first number: 1014 Enter the second number: beyond Invalid input: invalid literal for int() with base 10: 'beyond' Please try again Enter the first number: 1202 Enter the second number: Invalid input: invalid literal for int() with base 10: '' Please try again Enter the first number: 1014 Enter the second number: 0522 x / y is 1.9425287356321839 '''

最后

最后,還有finally子句,可用于在發(fā)生異常時執(zhí)行清理工作。這個子句是與try子句配套的。
finally子句非常適合用于確保文件或網(wǎng)絡套接字等得以關閉。
不管try子句中發(fā)生什么異常,都將執(zhí)行finally子句。

x = None try:x = 1 / 0 except NameError:print("Unknown variable") else:print("That went well!") finally:print('Cleaning up ...')del x

異常和函數(shù)

異常和函數(shù)有著天然的聯(lián)系。
如果不處理函數(shù)中引發(fā)的異常,它將向上傳播到調用函數(shù)的地方。
如果在那里也未得到處理,異常將繼續(xù)傳播,直至到達主程序(全局作用域)。
如果主程序中也沒有異常處理程序,程序將終止并顯示棧跟蹤消息。

def faulty():raise Exception('Something is wrong')def ignore_exception():faulty()def handle_exception():try:faulty()except:print('Exception handled')ignore_exception() ''' Exception Traceback (most recent call last) <ipython-input-6-5ac314d0ac0c> in <module>() ----> 1 ignore_exception()<ipython-input-5-6806e60d5602> in ignore_exception()3 4 def ignore_exception(): ----> 5 faulty()6 7 def handle_exception():<ipython-input-5-6806e60d5602> in faulty()1 def faulty(): ----> 2 raise Exception('Something is wrong')3 4 def ignore_exception():5 faulty()Exception: Something is wrong '''handle_exception()#結果為:Exception handled

faulty中引發(fā)的異常依次從faulty和ignore_exception向外傳播,最終導致顯示一條棧跟蹤消息。
調用handle_exception時,異常最終傳播到handle_exception,并被這里的try/except語句處理。

異常之禪

假設有一個字典,你要在指定的鍵存在時打印與之相關聯(lián)的值,否則什么都不做。

def describe_person(person):print('Description of',person['name'])print('Age:',person['age'])if 'occupation' in person:print('Occupation:',person['occupation'])

上面的這段代碼很直觀,但效率不高(雖然這里的重點是代碼簡潔),
因為它必須兩次查找occupation’鍵:
一次檢查這個鍵是否存在(在條件中),
另一次獲取這個鍵關聯(lián)的值,以便將其打印出來。

def describe_person(person):print('Description of',person['name'])print('Age:',person['age'])try:print('Occupation:',person['occupation'])except KeyError:pass

上面的這個函數(shù)直接假設存在’occupation’鍵。如果這種假設正確,就能省點事:直接獲取并打印值,而無需檢查這個鍵是否存在。如果這個鍵不存在,將引發(fā)KeyError異常,而except子句將捕獲這個異常。

檢查一個對象是否包含屬性write

try:obj.write except AttributeError:print('The object is not writeable') else:print('The object is writeable')

try子句只是訪問屬性write,而沒有使用它來做任何事情。
如果引發(fā)了AttributeError異常,說明對象沒有屬性write,否則就說明有這個屬性。

在很多情況下,相比于使用if/else,使用try/except語句更自然,也更符合Python的風格。

不那么異常的情況

如果你只想發(fā)出警告,指出情況偏離了正軌,可使用模塊warnings中的函數(shù)warn。
警告只顯示一次。如果再次運行最后一行代碼,什么事情都不會發(fā)生。

from warnings import warn warn('I like beyond band') ''' D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:2: UserWarning: I like beyond band '''

如果其他代碼在使用你的模塊,可使用模塊warnings中的函數(shù)filterwarnings來抑制你發(fā)出的警告(或特定類型的警告),并指定要采取的措施,如"error"或"ignore"。

from warnings import filterwarnings filterwarnings("ignore") warn("Anyone out there?") filterwarnings("error") warn("Something is very wrong!")''' UserWarning Traceback (most recent call last) <ipython-input-13-2678cd9c1908> in <module>()3 warn("Anyone out there?")4 filterwarnings("error") ----> 5 warn("Something is very wrong!")UserWarning: Something is very wrong! '''

上述引發(fā)的異常為UserWarning。發(fā)出警告時,可指定將引發(fā)的異常(即警告類別),但必須是Warning的子類。如果將警告轉換為錯誤,將使用你指定的異常。另外,還可根據(jù)異常來過濾掉特定類型的警告。

from warnings import filterwarnings filterwarnings("error") warn("This function is really old...",DeprecationWarning)''' DeprecationWarning Traceback (most recent call last) <ipython-input-14-db2d386b9ad9> in <module>()1 from warnings import filterwarnings2 filterwarnings("error") ----> 3 warn("This function is really old...",DeprecationWarning)DeprecationWarning: This function is really old... ''' from warnings import filterwarnings filterwarnings("ignore", category=DeprecationWarning) warn("Another deprecation warning.", DeprecationWarning) warn("Something else.")''' UserWarning Traceback (most recent call last) <ipython-input-15-2ae8758ff90f> in <module>()1 filterwarnings("ignore", category=DeprecationWarning)2 warn("Another deprecation warning.", DeprecationWarning) ----> 3 warn("Something else.")UserWarning: Something else. '''

小結

概念解釋
異常對象異常情況(如發(fā)生錯誤)是用異常對象表示的。對于異常情況,有多種處理方式;如果忽略,將導致程序終止。
引發(fā)異常可使用raise語句來引發(fā)異常。它將一個異常類或異常實例作為參數(shù),但你也可提供兩個參數(shù)(異常和錯誤消息)。如果在except子句中調用raise時沒有提供任何參數(shù),它將重新引發(fā)該子句捕獲的異常。
自定義的異常類你可通過從Exception派生來創(chuàng)建自定義的異常。
捕獲異常要捕獲異常,可在try語句中使用except子句。在except子句中,如果沒有指定異常類,將捕獲所有的異常。你可指定多個異常類,方法是將它們放在元組中。如果向except提供兩個參數(shù),第二個參數(shù)將關聯(lián)到異常對象。在同一條try/except語句中,可包含多個except子句,以便對不同的異常采取不同的措施。
else子句除except子句外,你還可使用else子句,它在主try塊沒有引發(fā)異常時執(zhí)行。
finally要確保代碼塊(如清理代碼)無論是否引發(fā)異常都將執(zhí)行,可使用try/finally,并將代碼塊放在finally子句中。
異常和函數(shù)在函數(shù)中引發(fā)異常時,異常將傳播到調用函數(shù)的地方(對方法來說亦如此)。
警告警告類似于異常,但(通常)只打印一條錯誤消息。你可指定警告類別,它們是Warning的子類。

本章介紹的新函數(shù)

函數(shù)描述
warnings.filterwarnings(action,category=Warning, …)用于過濾警告
warnings.warn(message, category=None)用于發(fā)出警告

總結

以上是生活随笔為你收集整理的第八章 异常的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。