1. 程式人生 > >錯誤和異常處理

錯誤和異常處理

選項 般的 out err 語法糖 stop 請求 特性 rect

Python有兩種錯誤很容易辨認:語法錯誤和異常。

1 什麽是異常?

異常即是一個事件,該事件會在程序執行過程中發生,影響了程序的正常執行。
一般情況下,在Python無法正常處理程序時就會發生一個異常。
如:有些是由於拼寫、配置、選項等等各種引起的程序錯誤,有些是由於程序功能處理邏輯不完善引起的漏洞,這些統稱為程序中的異常

異常是Python對象,表示一個錯誤。
當Python腳本發生異常時我們需要捕獲處理它,否則程序會終止執行。

常見異常如:

  1. 語法錯誤:SyntaxError:invalid syntax


    技術分享圖片 2018-04-02_215304.png

2.變量名不存在:NameError:name ‘b‘ is not defined


技術分享圖片 2018-04-02_215935.png

3.索引錯誤:IndexError: list index out of range


技術分享圖片 2018-04-02_220226.png

4.關鍵字錯誤:KeyError: ‘c‘


技術分享圖片 2018-04-02_220450.png

5.類型錯誤:TypeError: list indices must be integers, not str


技術分享圖片 2018-04-02_220741.png

6.參數傳值錯誤:ValueError: invalid literal for int() with base 10: ‘ab‘(主要發生在函數裏面)


技術分享圖片 2018-04-02_221813.png

7.屬性錯誤:AttributeError: A instance has no attribute ‘acc‘


技術分享圖片 2018-04-02_222234.png

8.輸入輸出錯誤:IOError


技術分享圖片 2018-04-02_222542.png

解決方案◆

  • 如果是拼寫、配置等等引起的錯誤,根據出錯信息進行排查錯誤出現的位置進行解決
  • 如果是程序設計不完善引起的漏洞,根據漏洞的情況進行設計處理漏洞的邏輯;

2 錯誤處理

錯誤的出現,在程序中一般會有兩種表現,一種是拼寫錯誤,一種是程序執行過程中出現的錯誤,這樣兩種不同的錯誤應該怎麽進行追蹤和處理呢?

2.1. 拼寫錯誤

常規情況下,拼寫錯誤只是在簡單的記事本等環境下進行開發時,容易手誤產生拼寫錯誤;當前開發環境下,我們經常使用一些半自動化的IDE開發工具,如pycharm等等,可以進行簡單的程序關鍵字的拼寫檢查以及程序結構的檢查,把一些簡單的拼寫問題掐死在萌芽之中

2.2程序運行時錯誤

程序運行過程中,也會出現各種各樣的錯誤,對於錯誤的出現和提示信息必須有一個比較明確的掌握,才能在後續的程序開發中快速的開發並且修復問題,這裏就會出現兩個步驟

  • 確定問題及問題出現的代碼行
  • 後續的問題處理【參考後面的異常處理】

3 異常處理方式

python程序中出現的異常信息,主要有兩種處理操作方式
? 直接處理異常,保證程序正常執行
? 拋出異常,告知調用者出現的重要錯誤信息

捕捉異常可以使用try/except語句。
(1). 直接處理異常

 c = int(input("請輸入整數選項:"))  print("用戶輸入了:%d" % c) 

 上述代碼,正常執行過程中,如果用戶輸入了字母會出現ValueError異常錯誤信息
請輸入整數選項:d
Traceback (most recent call last):
  File "D:/Py1801_B/DATE2/python高級/多線程/text.py", line 18, in <module>
    c = int(input("請輸入整數選項:"))
ValueError: invalid literal for int() with base 10: ‘d‘

捕捉異常

# 捕捉異常 1
try:      
    c = int(input("請輸入整數選項:"))                                       
    print("用戶輸入了:%d" % c)  # 處理異常
except:      
  print("出現了異常,用戶輸入了非法數據") 

通過try捕捉可能出現的異常,如果出現異常~並不讓程序直接崩潰退出,而是執行except中的代碼塊來處理出現的異常

上述代碼中,可以通過except處理在try代碼塊中出現的任意異常 

#捕捉異常2
try:      
  c = int(input("請輸入整數選項:"))     
  print("用戶輸入了:%d" % c)  # 處理指定異常
except ValueError:     
   print("出現了異常,用戶輸入了非法數據")

可以在except關鍵字後面,添加指定的異常名稱,來處理指定的異常;只有捕捉到該指定異常時except代碼塊才會執行

(2) .給異常信息定義別名

# 捕捉異常
try:
    c = int(input("請輸入整數選項:"))
    print("用戶輸入了:%d" % c)
# 處理指定的異常並獲取異常信息
except ValueError as e:
    print("出現了異常,用戶輸入了非法數據", e)

上述代碼中,在except中指定了處理的異常信息,並且通過as別名的方式將異常信息保存在了一個變量e中,後續可以通過變量e打印出現的異常信息

(3). 精確、同時處理多個異常

try:
    # 可能會出現文件找不到的異常:FileNotFoundError
    file = open("d:/test.txt", "r")

    # 可能會出現類型異常:ValueError
    c = int(input("請輸入整數選項:"))
    print("用戶輸入了:%d" % c)
# 指定需要處理的多個異常類型,包含在一個元組中
except (ValueError, FileNotFoundError) as e:
    print("出現了異常", e)

運行結果:
出現了異常 [Errno 2] No such file or directory: ‘d:/test.txt‘
如上述代碼所示,將多個需要處理的異常信息,進行精確的異常捕捉來提高程序代碼的容錯性能

(4). 精確、分步處理多個異常

try:
    # 可能會出現文件找不到的異常:FileNotFoundError
    file = open("d:/test.txt", "r")

    # 可能會出現類型異常:ValueError
    c = int(input("請輸入整數選項:"))
    print("用戶輸入了:%d" % c)
# 指定需要處理的多個異常類型,可以通過多個except疊加完成
except ValueError as e:
    print("出現了非法輸入異常", e)
except FileNotFoundError as e:
    print("文件操作出現異常", e)
except Exception as e:
    print("程序中出現了異常", e)

通過多個except疊加,進行異常的精確捕捉和精確處理

(5). 異常處理關鍵字finally

try:
    f = open("d:/oCam.rar", "rb")
except FileNotFoundError as e:
    print("文件操作出現異常", e)
except Exception as e:
    print("程序中出現了異常", e)
finally:
    # finally模塊中的代碼,不論是否出現異常,最終都會執行的代碼塊
    # 關閉文件,釋放資源
    f.close()

finally關鍵字比較特殊,主要是針對異常處理過程中的兩種分支進行一個統一的處理
代碼中根據是否出現異常會出現兩個分支
分支一:代碼中沒有異常,try中的代碼正常執行結束
分支二:代碼中出現異常,從異常代碼開始執行except中的代碼
但是不論執行那個分支,最後進行統一的資源回收時必須執行相同的代碼,所以finally關鍵字就出現了

(6). 異常處理關鍵字else

‘‘‘
try:
    # 可能出現異常的代碼
except ValueError as e:
    # 處理異常的代碼
except FileNotFoundError as e:
    # 處理異常的代碼
except:
    # 異常的通用處理
[else:]
    [# try中沒有異常,才會執行的代碼]
[finally:]
    [# 無論try中是否出現異常,都會執行的代碼]
‘‘‘
try:
    f = open("d:/test.txt", "rb")
except FileNotFoundError as e:
    print("文件操作出現異常", e)
except Exception as e:
    print("程序中出現了異常", e)
else:
    print("try中沒有出現異常")
finally:
    # finally模塊中的代碼,不論是否出現異常,最終都會執行的代碼塊
    # 關閉文件,釋放資源
    f.close()

else關鍵字是一種語法糖,主要是將try中的代碼進行了分離處理,將可能出現異常的代碼和之後的代碼分別安排在了不同的代碼塊中,主要目的是提高程序代碼的可讀性;但是實際項目操作過程中使用並不是很多,尤其是在try中或者except中出現了if語句的時候,else關鍵字使用反倒並不是盡如人意了。
(7). 拋出異常

# raise ValueError("出現錯誤")

try:
    c = int(input("請輸入選項:"))
    print("用戶輸入了選項:%d" % c)
except ValueError as e:
    # 轉換成一個比較清楚的異常
    # 但是問題是:直接使用系統的異常名稱,不是特別友好!
    raise ValueError("類型轉換錯誤")

拋出異常:是異常處理中經常用到的手段,主要是給函數的調用者拋出異常信息,要求調用的開發人員
對傳遞的數據有一個比較強制的約束

拋出異常:比較常用的手段就是拋出自定義異常
因為系統的某些內建異常,解讀起來還是比較有代溝的!在這樣的情況下,將比較復雜的系統異常
轉換成自定義的信息比較準確的異常數據展示,會更加友好!

4 自定義異常

自定義異常,是根據程序中功能的需要,定義的和項目本身結合比較緊密的個性化的異常信息;自定義異常應用比較廣泛,主要分兩個步驟進行操作

  • 定義自定義異常
  • 在合適的位置拋出異常

通常情況下,python中的自定義異常,都會選擇從系統標準異常Exception進行繼承實現,如下:

class MyException(Exception):
def __init__(self, message):
            self.message = message

def __str__(self):
            return “異常描述:%s” % self.message

拋出異常的操作比較簡單,通過關鍵字raise直接拋出異常即可

raise MyException(“出現了自定義異常”)

結合案例:

class MyException(Exception):
    ‘‘‘
    自定義異常
    ‘‘‘
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return "異常描述:%s" % self.msg

# 捕捉異常
try:
    # 用戶輸入數據
    num1 = float(input("請輸入第一個數據:"))
    num2 = float(input("請輸入第二個數據:"))
    res = num1 / num2
# 處理類型異常
except ValueError:
    print("只能輸入數字")
    raise MyException("只能輸入數字,但是用戶輸入了其他非數字字符")
# 處理0除數異常
except ZeroDivisionError:
    print("0不能做為除數")
    raise MyException("親,不能用0做為除數的")
# 正常結果
else:
    # 打印展示結果
    print("除法運算結果:%.2f" % res)
finally:
    print("計算過程結束")

運行結果:

請輸入第一個數據:q
Traceback (most recent call last):
只能輸入數字
計算過程結束
  File "D:/Py1801_B/DATE2/python高級/多線程/text.py", line 30, in <module>
    num1 = float(input("請輸入第一個數據:"))
ValueError: could not convert string to float: ‘q‘

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/Py1801_B/DATE2/python高級/多線程/text.py", line 36, in <module>
    raise MyException("只能輸入數字,但是用戶輸入了其他非數字字符")
__main__.MyException: 異常描述:只能輸入數字,但是用戶輸入了其他非數字字符

5 python標準異常

異常名稱描述
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 用戶代碼生成的警告

錯誤和異常處理