第16天:Python 錯誤和異常

2021-02-07 Python技術

作為 Python 初學者,在剛學習 Python 編程時,經常會看到一些報錯信息,這些報錯信息就是我們接下來要講的錯誤和異常。

我們在執行程序語句的時候,經常會看到命令行輸出報錯信息,例如:

>>> while True print('Hello world')  File "<stdin>", line 1, in ?    while True print('Hello world')                   ^SyntaxError: invalid syntax

這種報錯信息會阻止程序正常運行,也就是我們要介紹的錯誤和異常。

錯誤

我們說的錯誤指的是Python的語法錯誤,例如:

>>> if 1=1: print('always')  File "<stdin>", line 1    if 1=1: print('always')        ^SyntaxError: invalid syntax

上面例子中,在判斷相等的時候應該用''==',而不是用'=',執行的時候,語法解析器檢查到有錯誤,程序語句終止執行,並將錯誤的地方用上箭頭指出來。

語法錯誤很好解決,根據命令行提示的錯誤位置,檢查語法,改正即可。

異常

在Python中,即使你的代碼沒有語法錯誤,也不能保證程序按照你的想法運行完畢,因為在程序執行過程中也會有錯誤。程序運行期間檢測到的錯誤被稱為異常,例如:

>>> '1' + 2Traceback (most recent call last):  File "<stdin>", line 1, in ?TypeError: Can't convert 'int' object to str implicitly

大多數的異常都不會被程序處理,都以錯誤信息的形式顯示出來,如上例所示,提示信息告訴我們int類型不能和str類型相加。

錯誤提示信息會告訴我們異常發生的上下文,並以調用棧的形式顯示具體信息,提示信息的最後一行開頭會顯示錯誤類型名稱,上例中,錯誤類型為'TypeError',表示類型異常。

什麼是異常

異常是一個事件,該事件會在程序執行過程中發生,從而影響程序的正常執行。當 Python遇到無法處理的程序時,就會引發一個異常。在 Python 中,異常是一個對象,用於表示一個錯誤,當 Python腳本發生異常時我們需要捕獲和處理它,否則程序會終止執行。

處理異常

Python 提供了 try/except語句用來捕獲和處理異常。try 語句用來檢測語句塊中是否有錯誤,except 語句則用來捕獲 try 語句中的異常,並進行處理,附加的 else 可以在 try 語句沒有異常時執行。

語法

下面以最簡單的 try...except...else 為例:

try:    statement(s)            # 要檢測的語句塊except exception:    deal_exception_code # 如果在 try 部份引發了 'exception' 異常except exception2, e:    deal_exception2_code # 如果引發了 'exception2' 異常else:    no_exception_happend_code #如果沒有異常發生

try 語句的執行邏輯如下:

首先,執行 try 子句 (try 和 except 關鍵字之間的(多行)語句)。

如果沒有異常發生,則跳過 except 子句 並完成 try 語句的執行。

如果在執行try 子句時發生了異常,則跳過該子句中剩下的部分。然後,如果異常的類型和 except 關鍵字後面的異常匹配,則執行 except 子句,然後繼續執行 try 語句之後的代碼。

如果發生的異常和 except 子句中指定的異常不匹配,則將其傳遞到外部的 try 語句中;如果沒有找到處理程序,則它是一個 未處理異常,執行將停止並顯示錯誤消息。

如果 try 語句執行時沒有發生異常,那麼將執行 else 語句後的語句(如果有 else 的話),然後控制流通過整個 try 語句。

基類

如果發生的異常和 except 子句中的類是同一個類或者是它的基類,則異常和 except 子句中的類是兼容的(但反過來則不成立 --- 列出派生類的 except 子句與基類兼容)。

實例
class BException(Exception):  #繼承Exception基類    pass
class CException(BException): #繼承BException基類 pass
class DException(CException): #繼承CException基類 pass
for cls in [BException, CException, DException]: try: raise cls() #拋出異常 except DException: print("D") except CException: print("C") except BException: print("B")
#輸出BCD

請注意如果 except 子句被顛倒(把 except BException 放到第一個),它將列印 B,B,B --- 因為DException類繼承CException類,CException類繼承BException類,將 except BException 放到第一個可以匹配這三個異常,後面的 except 就不會執行。

不帶異常類型的 except

Python可以在所有 except 的最後加上 except 子句,這個子句可以省略異常名,以用作通配符。它可以捕獲前面任何 except (如果有的話)沒有捕獲的所有異常。

try:    statement(s)            # 要檢測的語句塊except exception:    deal_exception_code # 如果在 try 部份引發了 'exception' 異常except :    deal_all_other_exception2_code # 處理全部其它異常else:    no_exception_happend_code #如果沒有異常發生

實例
try:    raise BException()  #拋出異常except DException:    print("D")except:    print("處理全部其它異常") #處理全部其它異常
#輸出處理全部其它異常

except 語句捕獲多種異常類型

一個 try 語句可能有多個 except 子句,以指定不同異常的處理程序,最多會執行一個處理程序。處理程序只處理相應的 try 子句中發生的異常,而不處理同一 try 語句內其他處理程序中的異常。一個 except 子句可以將多個異常命名為帶括號的元組。

try:    statement(s)            # 要檢測的語句塊except exception:    deal_exception_code # 如果在 try 部份引發了 'exception' 異常except (Exception1[, Exception2[,...ExceptionN]]]) :    deal_all_other_exception2_code # 處理多個異常else:    no_exception_happend_code #如果沒有異常發生

實例
try:    raise BException()  #拋出異常except (BException, DException):    print("D")except:    print("處理全部其它異常") #處理全部其它異常else:    print("沒有異常發生") #沒有異常發生
#輸出D

try - finally 語句

finally 語句用於無論是否發生異常都將執行最後的代碼。

try:    # <語句>finally:    # <語句>    #退出try時總會執行

實例
try:    raise BException()  #拋出異常except (BException, DException):    print("D")except:    print("處理全部其它異常") #處理全部其它異常else:    print("沒有異常發生") #沒有異常發生finally:    print("你們繞不過我,必須執行") #必須執行的代碼    #輸出D你們繞不過我,必須執行

這裡注意 finally 和 else 的區別,finally 是無論是否有異常都會執行,而 else 語句只有沒有異常時才會執行。也就是說如果沒有異常,那麼 finally 和 else 都會執行。

異常的參數

except 子句可以在異常名稱後面指定一個變量。這個變量和一個異常實例綁定,它的參數是一個元組,通常包含錯誤字符串,錯誤數字,錯誤位置,存儲在 .args 中。為了方便起見,異常實例定義了__str__() ,因此可以直接列印參數而無需引用 .args。

try:    # 正常的操作 .except ExceptionType as inst:    # 可以在這輸出 inst 的值

實例
try:    x = 1 / 0  # 除數為0except ZeroDivisionError as err: #為異常指定變量err    print("Exception")    print(err.args) #列印異常的參數元組    print(err) #列印參數,因為定義了__str__()
#輸出Exception('division by zero',)division by zero

觸發異常

Python 提供了 raise 語句用於手動引發一個異常。

語法
raise [Exception [, args [, traceback]]]

參數說明
Exception:異常的類型,例如 ZeroDivisionErrorargs:異常參數值,可選,默認值 "None"traceback:可選,用於設置是否跟蹤異常對象

異常參數值可以是一個字符串,類或對象

實例
def diyException(level):    if level > 0:        raise Exception("raise exception", level)  #主動拋出一個異常,並且帶有參數        print('我是不會執行的') #這行代碼不會執行
try: diyException(2) #執行異常方法except Exception as err: #捕獲異常 print(err) #列印異常參數 #輸出('raise exception', 2)

為了能夠捕獲異常,"except"語句必須有用相同的異常來拋出類對象或者字符串。如果要捕獲上面代碼拋出的異常,except 語句應該如下所示:

#定義函數def diyException(level):    if level > 0:        raise Exception("error level", level)  #主動拋出一個異常,並且帶有參數        print('我是不會執行的') #這行代碼不會執行
try: diyException(2) #執行異常方法except 'error level' as err: #捕獲異常 print(err) #列印異常參數
#輸出Traceback (most recent call last): File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module> diyException(2) #執行異常方法 File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException raise Exception("error level", level) #主動拋出一個異常,並且帶有參數Exception: ('error level', 2)

當然,我們也可以通過 traceback 來捕獲異常:

import traceback
#定義函數def diyException(level): if level > 0: raise Exception("error level", level) #主動拋出一個異常,並且帶有參數 print('我是不會執行的') #這行代碼不會執行
try: diyException(2) #執行異常方法except Exception: #捕獲異常 traceback.print_exc()#輸出Traceback (most recent call last): File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module> diyException(2) #執行異常方法 File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException raise Exception("error level", level) #主動拋出一個異常,並且帶有參數Exception: ('error level', 2)

用戶自定義異常

除了使用 Python 內置的異常,我們還可以創建自己的異常類型。創建自己的異常非常簡單,只需要創建一個類,並繼承 Exception 類或其子類。

下面的代碼創建了一個異常 DiyError 繼承自 Python 內置的 RuntimeError,用於在異常觸發時輸出更多的信息。

#自定義異常class DiyError(RuntimeError):    def __init__(self, arg):        self.args = arg
try: raise DiyError("my diy exception") #觸發異常except DiyError as e: print(e)

定義好了之後,我們就可以在 except 語句後使用 DiyError 異常,變量 e 是用於創建 DiyError 類的實例。我們也可以通過 raise 語句手動觸發這個異常。

預定義的清理行為

一些對象定義了標準的清理行為,無論系統是否成功的使用了它,一旦不需要它了,那麼這個標準的清理行為就會執行。

for line in open("myfile.txt"):    print(line, end="")

上面這個例子嘗試打開一個文件,然後把內容列印出來。但是有一個問題:當執行完畢後,程序沒有關閉文件流,文件會保持打開狀態。

關鍵詞 with 語句就可以保證諸如文件之類的對象在使用完之後一定會正確的執行他的清理方法。

with open("myfile.txt") as f:    for line in f:        print(line, end="")

以上這段代碼執行完畢後,就算在處理過程中出問題了,文件 f 總是會關閉。這裡面的原理就是使用了 finally 機制,有興趣的可以去深入了解一下。

總結

本節給大家介紹了 Python 錯誤和異常的使用,掌握了錯誤和異常的處理,可以極大地提高程序的健壯性,為程序的持續完整運行提供了保障。


PS:公號內回復 :Python,即可進入Python 新手學習交流群,一起100天計劃!



相關焦點

  • Python學習第50課-處理錯誤和異常
    【每天幾分鐘,從零入門python編程的世界!】在工作當中會經常出現意料不到的錯誤和異常,就需要我們對可能出現的錯誤和異常進行預判,然後加上捕獲和處理錯誤異常的代碼,否則,程序在運行過程中,遇到錯誤和異常就會crash崩潰,無法繼續向下執行。●Python的錯誤種類:①語法錯誤,或稱解析錯誤。
  • python教程之九錯誤和異常處理
    Python 有兩種錯誤很容易辨認:語法錯誤和異常。語法錯誤語法分析器指出了出錯的一行,並且在最先找到的錯誤的位置標記了顏色,如下所示。 異常Python 程序的語法是正確的,在運行它的時候,也有可能發生錯誤。運行期檢測到的錯誤被稱為異常。
  • 16-python中的異常
    通過前兩天的文章14-python中的函數,15-再敘python中的函數我們對python中有關函數的知識有了系統的認識和學習,今天我們將接著來看一下python中的異常。(一)Bug的由來和分類    "Bug"一詞的原意是"昆蟲"或"蟲子";而在電腦系統或程序中隱藏著的一些未被發現的缺陷或問題,人們也叫它"bug"。
  • [Python]文件與異常的錯誤處理
    [Python]文件與異常的錯誤處理1.文件基本操作:打開文件,處理文件,關閉文件the_file = open("sketch.txt", 'r')line_content = the_file.readline()  # 不指定readline的參數,讀取一整行print(line_content)# 輸出了sketch.txt的第一行數據
  • Python系列特別篇-錯誤和異常
    語法錯誤又稱解析錯誤,這是初學者最容易碰到的錯誤了,原因是輸入的內容Python解析器解析不通過導致的。即便是語法、縮進都是OK的,也不代表程序就能夠在運行時不會引發錯誤。在執行時檢測到的錯誤被稱為 異常,異常並不致命,但我們仍然需要學會處理它。
  • python入門——Python中異常處理
    python大數據課堂已經開始了。想轉行大數據,數據挖掘,機器學習,人工智慧的小夥伴可以關注啦。上一篇帶大家了解了python中的I/O函數。今天我們來繼續了解python中的異常處理。調試環境以python3.6環境為例。需要代碼和demo的朋友可以搜索「欒鵬全棧」到我的CSDN博客。
  • Python異常處理
    問題描述大家在使用python語言寫代碼的時候難免會出一些錯誤,而才入門的朋友們往往不知道是哪裡出了錯或者不知道自己錯在哪裡、什麼錯誤。所以我們要知道是哪行代碼出錯,其次室錯誤的類型是什麼,錯在那個細節,逐步分析,從而解決錯誤並改正。
  • python異常處理與上下文管理器
    作者丨王翔丨來研丨清風Pythonpython異
  • 一行代碼簡化Python異常信息:錯誤清晰指出,排版簡潔美觀
    那麼,Python異常輸出美化工具PrettyErrors了解一下?只需一個import,報錯也能整齊劃一,錯誤代碼位置、錯誤原因清晰明了,一眼就能看清。debug仿佛都沒有那麼痛苦了。一行代碼簡化報錯先來試試一個簡單的錯誤。
  • Python基礎 | 新手學Python時常見的語法錯誤和異常
    然後各種艱難的複查發現可能是循環語句缺少冒號啊、用了中文的標點符號啊、引號/括號等少了一個或者無法匹配啊、函數方法或變量名拼寫錯誤啊等等。在Python編程中有兩種可區分的報錯:語法錯誤 和 異常。語法錯誤又稱解析錯誤,是我們在剛接觸學習Python 時最容易遇到的錯誤,區區別於異常而言,語法錯誤非程序執行時的邏輯錯誤;即使語句或表達式在語法上是正確的,但在嘗試執行時,它仍可能會引發錯誤,而這個在執行時檢測到的邏輯錯誤被稱為異常。
  • python面向對象之異常處理
    異常的概念 程序在運行時,如果 `Python 解釋器` 遇到 到一個錯誤,會停止程序的執行,並且提示一些錯誤信息,這就是 異常 程序停止執行並且提示錯誤信息 這個動作,我們通常稱之為:拋出(raise)異常> 程序開發時,很難將 所有的特殊情況 都處理的面面俱到,通過 異常捕獲 可以針對突發事件做集中的處理,從而保證程序的 穩定性和健壯性
  • python基礎---異常處理
    程序的異常處理今天霖小白心血來潮想來分享一下python基礎中的如何異常處理,使程序有更好的用戶體驗。前言python程序對用戶的輸入有一定的要求,所以當實際輸入不滿足程序要求時,可能在程序運行過程中會直接報錯無法進行下一步的運行。
  • 一文教你讀懂 Python 中的異常信息
    雖然 Python 的 Traceback 提示信息看著挺複雜,但是裡面豐富的信息,可以幫助你診斷和修復代碼中引發異常的原因,以及定位到具體哪個文件的哪行代碼出現的錯誤,所以說學會看懂 Traceback 信息是非常重要的,另外在面試的時候也經常會問到 Python 中的異常類型及其含義,那麼,接下來就讓我們對其進行詳細理解。
  • Python-異常與錯誤
    那就讓我們進入本章的學習吧Python 有兩種錯誤很容易辨認:語法錯誤和異常。Python assert(斷言)用於判斷一個表達式,在表達式條件為 false 的時候觸發異常。語法分析器指出了出錯的一行,並且在最先找到的錯誤的位置標記了一個小小的箭頭。異常即便 Python 程序的語法是正確的,在運行它的時候,也有可能發生錯誤。運行期檢測到的錯誤被稱為異常。
  • Python基礎教程(一) - 錯誤和異常
    程式設計師的一生中,錯誤幾乎每天都在發生。在過去的一個時期,錯誤要麼對程序是致命的,要麼產生一堆無意義的輸出。所以,人們需要一個柔和的處理錯誤的方法,而不是終止執行。當然,這一切都是在異常和異常處理出現之前的事了。
  • 初學Python常見異常錯誤
    初學Python常見錯誤忘記寫冒號誤用=錯誤 縮緊變量沒有定義中英文輸入法導致的錯誤
  • python 異常處理
    2) 具體工廠角色(Stone_Axe_Factory,Steel_Axe_Factory):它含有和具體業務邏輯有關的代碼。由應用程式調用以創建對應的具體產品的對象。3) 抽象產品角色(Axe):它是具體產品繼承的父類或者是實現的接口。在python中抽象產品一般為父類。
  • Python小課堂|錯誤和異常
    Python 有兩種錯誤很容易辨認:語法錯誤和異常。Python assert(斷言)用於判斷一個表達式,在表達式條件為 false 的時候觸發異常。即便 Python 程序的語法是正確的,在運行它的時候,也有可能發生錯誤。運行期檢測到的錯誤被稱為異常。
  • python入門學習異常處理類型
    前言異常是指在程序執行過程中發生的一個事件,影響了程序的正常執行,例如:0做了分母。異常是Python對象,表示一個錯誤。當Python腳本發生異常時我們需要捕獲處理它,否則程序會終止執行。在Java語言中我們知道異常的常用結構為try catch組成,有時也會用到finally,那麼在python中異常是如何來處理的呢?python中的異常處理1.python異常簡單語法python異常的簡單語法為try-except-else語法,注意這裡的關鍵字是except而不是Exception,這與java是有區別的。
  • 一篇文章幫你搞定Python異常處理
    異常與錯誤程序錯誤分類(兩類)語法錯誤(這種錯誤,根本過不了python解釋器的語法檢測,必須在程序執行前就改正)邏輯錯誤(邏輯錯誤)#用戶輸入不完整(比如輸入為空)或者輸入非法(輸入不是數字)num=input(">>: ")int(num)#無法完成計算res1=1/0res2