1、錯誤與異常python
程序中不免會出現錯誤,而錯誤分爲兩種git
一、語法錯誤:這種錯誤,根本過不了 Python 解釋器的語法檢測,必須在程序執行前就改正程序員
二、邏輯錯誤:好比用戶輸入的不合適等一系列錯誤安全
那什麼是異常呢?ide
異常是程序運行時發生錯誤的信號,一旦程序出錯就會產生一個異常,若是該異常沒有被應用程序處理,那麼該異常就會拋出來,程序的執行也隨之終止編碼
異常包含三個部分:spa
一、traceback 異常的追蹤信息操作系統
二、異常的類型:在 Python 中不一樣的異常能夠用不一樣的類型( Python 中統一類與類型,類型即類)去標識,不一樣的類對象標識不一樣的異常,一個異常標識一種錯誤3d
三、異常的信息code
常見的異常:
BaseException 全部異常的基類 SystemExit 解釋器請求退出 KeyboardInterrupt 用戶中斷執行(一般是輸入^C) Exception 常規錯誤的基類 StopIteration 迭代器沒有更多的值 GeneratorExit 生成器(generator)發生異常來通知退出 StandardError 全部的內建標準異常的基類 ArithmeticError 全部數值計算錯誤的基類 FloatingPointError 浮點計算錯誤 OverflowError 數值運算超出最大限制 ZeroDivisionError 除(或取模)零 (全部數據類型) AssertionError 斷言語句失敗 AttributeError 對象沒有這個屬性 EOFError 沒有內建輸入,到達EOF 標記 EnvironmentError 操做系統錯誤的基類 IOError 輸入/輸出操做失敗 OSError 操做系統錯誤 WindowsError 系統調用失敗 ImportError 導入模塊/對象失敗 LookupError 無效數據查詢的基類 IndexError 序列中沒有此索引(index) KeyError 映射中沒有這個鍵 MemoryError 內存溢出錯誤(對於Python 解釋器不是致命的) NameError 未聲明/初始化對象 (沒有屬性) UnboundLocalError 訪問未初始化的本地變量 ReferenceError 弱引用(Weak reference)試圖訪問已經垃圾回收了的對象 RuntimeError 通常的運行時錯誤 NotImplementedError 還沒有實現的方法 SyntaxError Python 語法錯誤 IndentationError 縮進錯誤 TabError Tab 和空格混用 SystemError 通常的解釋器系統錯誤 TypeError 對類型無效的操做 ValueError 傳入無效的參數 UnicodeError Unicode 相關的錯誤 UnicodeDecodeError Unicode 解碼時的錯誤 UnicodeEncodeError Unicode 編碼時錯誤 UnicodeTranslateError Unicode 轉換時錯誤 Warning 警告的基類 DeprecationWarning 關於被棄用的特徵的警告 FutureWarning 關於構造未來語義會有改變的警告 OverflowWarning 舊的關於自動提高爲長整型(long)的警告 PendingDeprecationWarning 關於特性將會被廢棄的警告 RuntimeWarning 可疑的運行時行爲(runtime behavior)的警告 SyntaxWarning 可疑的語法的警告 UserWarning 用戶代碼生成的警告
2、異常處理
一、什麼是異常處理?
Python 解釋器檢測到錯誤,觸發異常(也容許程序員本身觸發異常)
程序員編寫特定的代碼,專門用來捕捉這個異常(這段代碼與程序邏輯無關,與異常處理有關)
若是捕捉成功則進入另一個處理分支,執行你爲其定製的邏輯,使程序不會崩潰,這就是異常處理
二、爲什麼要進行異常處理?
Python 解析器去執行程序,檢測到了一個錯誤時,觸發異常,異常觸發後且沒被處理的狀況下,程序就在當前異常處終止,後面的代碼不會運行,誰會去用一個運行着忽然就崩潰的軟件。
因此你必須提供一種異常處理機制來加強你程序的健壯性與容錯性
三、如何進行異常處理
首先須知,異常是由程序的錯誤引發的,語法上的錯誤跟異常處理無關,必須在程序運行前就修正
① 使用 if 判斷
n = input('>>: ') # 輸入一個字符串試試
if n.isdigit(): int(n) # 咱們的正統程序放到了這裏,其他的都屬於異常處理範疇
elif n.isspace(): print('輸入的是空格, 就執行我這裏的邏輯') elif len(n) == 0: print('輸入的是空, 就執行我這裏的邏輯') else: print('其餘情狀況, 執行我這裏的邏輯') ''' 問題一: 使用if的方式咱們只爲第一段代碼加上了異常處理,但這些if,跟你的代碼邏輯並沒有關係,這樣你的代碼會由於可讀性差而不容易被看懂 問題二: 這只是咱們代碼中的一個小邏輯,若是相似的邏輯多,那麼每一次都須要判斷這些內容,就會倒置咱們的代碼特別冗長。 '''
總結:
一、if 判斷式的異常處理只能針對某一段代碼,對於不一樣的代碼段的相同類型的錯誤你須要寫重複的 if 來進行處理。
二、在你的程序中頻繁的寫與程序自己無關,與異常處理有關的 if ,會使得你的代碼可讀性極其的差
三、if 是能夠解決異常的,只是存在一些問題,因此,千萬不要妄下定論 if 不能用來異常處理
② Python 爲每一種異常定製了一個類型,而後提供了一種特定的語法結構用來進行異常處理
一、語法
try:
被檢測的代碼塊
except 異常類型:
try中一旦檢測到異常,就執行這個位置的邏輯
二、異常類只能用來處理指定的異常狀況,若是非指定異常則沒法處理
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print(e) # 沒有捕獲到異常,程序直接報錯
三、多分支
try: print("===1") print("===2") d = {'x': 1, 'y': 2} d['z'] print("===3") l = [1,2,3] l[100] except IndexError as e: print("IndexError", e) except KeyError as e: print("KeyError", e) # 能夠將多個異常放在一塊兒 # except (IndexError, KeyError) as e: # print("Error", e)
else: print("異常處理") # else必須放到後面(但不是最後), else的子代碼塊會在被檢測的代碼沒有異常的狀況下運行
finally: print("不管被檢測的代碼有沒有異常, 都會執行") print("other code")
finally 通常用於資源回收的操做,好比在 try 裏面打開了一個文件,若是程序有異常,後面的代碼不會執行,若是沒有被 except 捕捉到,else 也不會執行,這時文件就沒法關閉,使用 finally 即可以作關閉文件回收資源的操做
四、萬能異常:能夠捕獲任意異常
try: print("===1") print("===2") d = {'x': 1, 'y': 2} # d['z']
# xx
print("===3") l = [1,2,3] l[100] except Exception as e: print(e) print("other code")
五、主動觸發異常
print("===1")
print("===2")
raise TypeError("類型錯誤")
print("===3")
raise應用場景
1. 當資源被無限佔用的狀況下, 須要讓程序終止, 這種狀況須要主動拋出異常
2. 自定義一些規則的狀況下可使用
class People(): def __init__(self, name, age): self.__name = name self.__age = age def tell_info(self): print(self.__name, self.__age) def set_info(self, name, age): self.__name = name self.__age = age obj = People("egon", 18) # print(obj.__dict__)
obj.tell_info() # 這樣寫不嚴謹, 能隨意修改類型
obj.set_info(3213, "dsa") obj.tell_info() # ========================================
class People(): def __init__(self, name, age): self.__name = name self.__age = age def tell_info(self): print(self.__name, self.__age) def set_info(self, name, age): if not isinstance(name, str): raise TypeError("名字必須是str類型") if not isinstance(age, int): raise TypeError("年齡必須是int類型") self.__name = name self.__age = age obj = People("xi", 18) # print(obj.__dict__)
obj.tell_info() obj.set_info("yan", 12) obj.tell_info()
六、自定義異常
class MyException(BaseException): def __init__(self, msg): super().__init__() self.msg = msg def __str__(self): return "<%s>" %self.msg raise MyException('我自定義的異常')
七、斷言
# 讓列表的長度爲5, 若是不是, 就不作下半部分
print("上半部分, 生產數據") l = [1,2,3,4,5] if len(l) != 5: raise TypeError("列表的長度必須爲5") print("下半部分, 處理數據") # 斷言
print("上半部分, 生產數據") l = [1,2,3,4] assert len(l) == 5
print("下半部分, 處理數據")
try...except 這種異常處理機制就是取代if那種方式,讓你的程序在不犧牲可讀性的前提下加強健壯性和容錯性
異常處理中爲每個異常定製了異常類型(Python中統一類與類型,類型即類),對於同一種異常,一個 except 就能夠捕捉到,能夠同時處理多段代碼的異常(無需寫多個 if 判斷)減小了代碼,加強了可讀性
使用 try...except 的方式
一、把錯誤處理和真正的工做分開來
二、代碼更易組織,更清晰,複雜的工做任務更容易實現
三、毫無疑問,更安全了,不至於因爲一些小的疏忽而使程序意外崩潰了
3、何時用異常處理
try...except 應該儘可能少用,由於它自己就是你附加給你的程序的一種異常處理的邏輯,與你的主要的工做是沒有關係的
這種東西加的多了,會致使你的代碼可讀性變差,只有在有些異常沒法預知的狀況下,才應該加上 try...except,其餘的邏輯錯誤應該儘可能修正