前言:之前工作時用python完成一個利用串口發SCPI與單片機交互通信的命令列窗口,在實現功能的時候發現用python對數據結果無論是最終正確值的回傳或錯誤值的回傳都可以直接return給主介面。顯然直接return不同意義的資料是不行的,所以採用異常機制來處理錯誤值的資料。因為之前對異常這方面了解的比較少,在此查了點資料並整理個小筆記。
文章目錄
- 一、對異常的理解
- 1、什麼是異常
- 2、錯誤和異常的區別
- 3、常見python異常種類
- 二、python五大異常處理機制
- 1、預設例外處理機制
- 2、try....except....處理機制
- #3、try...except...finally.....處理機制
- 4、assert斷言處理機制
- #5、with...as處理機制
- 三、python異常自訂
- 1、異常自訂
- 2、異常拋出raise
- 3.異常捕獲
- 四、異常使用注意事項
- 1、不要太依賴異常機制
- 2、不要在try 區塊中引入太多的程式碼
- 3、不要忽略捕獲到的例外
總結
(免費學習推薦:python影片教學#)
一、對異常的理解
1、什麼是異常
異常即“與正常情況不同”,何為正常?正常便是解釋器在解釋程式碼時,我們所寫的程式碼符合解釋器定義的規則,即為正常,當解釋器發現某段程式碼符合語法但有可能出現不正常的情況時,解釋器便會發出一個事件,中斷程式的正常執行。這個中斷的訊號便是一個異常訊號。所以,整體解釋就是,在解釋器發現到程式出現錯誤的時候,則會產生一個異常,若程式沒有處理,則會將該異常拋出,程式的運作也隨之終止。我們可以在一個空白的.py檔中寫一句int(「m」),運行後結果如下。
這一串字體為解釋器拋出的一系列錯誤訊息,因為int()傳入的參數只支援數字字串和數字,顯然'm'不屬於數字字串傳入參數錯誤所以解釋器報“valueError”的錯誤。
2、錯誤和異常的區別
對於python錯誤的概述:它指的是程式碼運行前的語法或邏輯錯誤。拿常規語法錯誤來說,當我們寫的程式碼過不了語法偵測時,則會直接出現語法錯誤,必須在程式執行前就改正,不然寫的程式碼將毫無意義,程式碼是不運作的,也無法捕獲得到。舉個例子,在.py檔輸入if a = 1 print(“hello”),輸出結果如下:
Traceback (most recent call last): File "E:/Test_code/test.py",line 1 if a = 1 print("hello") ^SyntaxError: invalid syntax
函數print() 被檢查到有錯誤,是它前面缺少了一個冒號: ,所以解析器會復現句法錯誤的那行程式碼,並用一個小「箭頭」指向行裡偵測到的第一個錯誤,所以我們可以直接找到對應的位置修改其語法。當然除了語法錯誤,還有很多程式奔潰的錯誤,如記憶體溢位等,這類錯誤往往比較隱密。
相較於錯誤,python異常主要在程式執行過程中,程式遇見邏輯或演算法問題,這時解釋器如果可以處理,則沒問題,如果處理不了,便直接終止程序,便將異常拋出,如第1小點的int('m')例子,因為參數傳入錯誤導致程式出錯。這種因為邏輯產生的異常五花八門,還好我們的解釋器都內建好了各種異常的種類,讓我們知道是什麼樣的異常出現,好讓我們「對症下藥」。
這裡注意一點,上述語法錯誤是可辨識的錯誤,所以解釋器也會預設拋出一個SyntaxError異常訊息回饋給程式設計師。所以本質上大部分錯誤都是可輸出列印的,只是因為錯誤程式碼不運行,也就沒辦法處理,所以捕捉錯誤的異常訊息就變得沒意義。
3、常見python異常種類
這裡貼上我們在寫程式碼時最常見的異常類型,如果遇到其他種類的異常,當然是選擇白度啦~
異常名稱 | 名稱解析 |
---|---|
#BaseException | 所有例外的基底類別 |
SystemExit | 解釋器請求退出 |
KeyboardInterrupt | 使用者中斷執行(通常是輸入^C) |
Exception | 常規錯誤的基類 |
迭代器沒有更多的值 | |
生成器(generator)發生異常來通知退出 | |
所有的內建標準異常的基底類別 | |
所有數值計算錯誤的基底類別 | ##FloatingPointError |
OverflowError | |
ZeropisionError | |
AssertionError | |
AttributeError | |
EOFError | |
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 | 使用者程式碼產生的警告 |
# 二、python五大异常处理机制 我们明白了什么是异常后,那么发现异常后怎么处理,便是我们接下来要解决的问题。这里将处理异常的方式总结为五种。 1、默认异常处理机制 “默认”则说明是解释器默认做出的行为,如果解释器发现异常,并且我们没有对异常进行任何预防,那么程序在执行过程中就会中断程序,调用python默认的异常处理器,并在终端输出异常信息。刚才举过的例子:int(“m”),便是解释器因为发现参数传入异常,这种异常解释器“无能为力”,所以它最后中断了程序,并将错误信息打印输出,告诉码农朋友们:你的程序有bug!!! 2、try…except…处理机制 我们把可能发生错误的语句放在try语句里,用except来处理异常。每一个try,都必须至少有一个或者多个except。举一个最简单的例子如下,在try访问number的第500个元素,很明显数组越界访问不了,这时候解释器会发出异常信号:IndexError,接着寻找后面是否有对应的异常捕获语句except ,如果有则执行对应的except语句,待except语句执行完毕后,程序将继续往下执行。如果没有对应的except语句,即用户没有处理对应的异常,这时解释器会直接中断程序并将错误信息打印输出。 number = 'hello'try: print(number[500]) #数组越界访问except IndexError: print("下标越界啦!")except NameError: print("未声明对象!")print("继续运行...") 输出结果如下,因为解释器发出异常信号是IndexError,所以执行下标越界语句。 下标越界啦! 继续运行... 为了解锁更多用法,我们再将例子改一下,我们依然在try访问number的第500个元素,造成访问越界错误,这里的except用了as关键字可以获得异常对象,这样子便可获得错误的属性值来输出信息。 number = 'hello'try: print(number[500]) #数组越界访问except IndexError as e: print(e)except Exception as e: #万能异常 print(e)except: #默认处理所有异常 print("所有异常都可处理")print("继续运行...") 输出结果如下所示,会输出系统自带的提示错误:string index out of range,相对于解释器因为异常自己抛出来的一堆红色刺眼的字体,这种看起来舒服多了(能够“运筹帷幄”的异常才是好异常嘛哈哈哈)。另外这里用到“万能异常”Exception,基本所有没处理的异常都可以在此执行。最后一个except表示,如果没有指定异常,则默认处理所有的异常。 string index out of range继续运行... 3、try…except…finally…处理机制 finally语句块表示,无论异常发生与否,finally中的语句都要执行完毕。也就是可以很霸气的说,无论产生的异常是被except捕获到处理了,还是没被捕获到解释器将错误输出来了,都统统要执行这个finally。还是原来简单的例子加上finally语句块如下,代码如下: number = 'hello'try: print(number[500]) #数组越界访问,抛出IndexError异常except IndexError: print("下标越界啦!")finally: print("finally!")print("继续运行...") #运行 结果如下,数据越界访问异常被捕获到后,先执行except 语句块,完毕后接着执行了finally语句块。因为异常被执行,所以后面代码继续运行。 下标越界啦!finally! 继续运行... 对try语句块进行修改,打印abc变量值,因为abc变量没定义,所以会出现不会被捕获的NameError异常信号,代码如下所示: number = 'hello'try: print(abc) #变量未被定义,抛出NameError异常except IndexError: print("下标越界啦!")finally: print("finally!")print("继续运行...") #不运行 结果如下,因为NameError异常信号没法被处理,所以解释器将程序中断,并将错误信息输出,但这过程中依然会执行finally语句块的内容。因为程序被迫中断了,所以后面代码不运行。 finally! #异常没被捕获,也执行了finallyTraceback (most recent call last): File "E:/Test_code/test.py",line 3,in <module> print("abc")NameError: name 'abc' is not defined 理解到这里,相信:try…finally…这种机制应该也不难理解了,因为省略了except 捕获异常机制,所以异常不可能被处理,解释器会将程序中断,并将错误信息输出,但finally语句块的内容依然会被执行。例子代码如下: number = 'hello'try: print(abc) #变量未被定义,抛出NameError异常finally: print("finally!")print("继续运行...") 运行结果: finally! #异常没被捕获,也执行了finallyTraceback (most recent call last): File "E:/Test_code/test.py",line 3,in <module> print("abc")NameError: name 'abc' is not defined 4、assert断言处理机制 assert语句先判断assert后面紧跟的语句是True还是False,如果是True则继续往下执行语句,如果是False则中断程序,将错误信息输出。 assert 1 == 1 #为True正常运行assert 1 == 2 #为False,终止程序,错误信息输出 5、with…as处理机制 with…as一般常用在文件处理上,我们平时在使用类似文件的流对象时,使用完毕后要调用close方法关闭,很麻烦,这里with…as语句提供了一个非常方便且人性的替代方法,即使突发情况也能正常关闭文件。举个例子代码如下,open打开文件后将返回的文件流对象赋值给fd,然后在with语句块中使用。 with open('e:/test.txt','r') as fd: fd.read() print(abc) #变量未被定义,程序终止,错误信息输出print("继续运行...") 正常情况下,这里的with语句块完毕之后,会自动关闭文件。但如果with语句执行中发生异常,如代码中的变量未定义异常,则会采用默认异常处理机制,程序终止,错误信息输出,后面代码不被运行,文件也会正常关闭。 三、python异常自定义 说了这么多异常的使用,终于可以回到我前言所说的在实际项目中存在的问题,即错误码的返回和数值的返回是冲突的(因为错误码也是数值),这时候便可以用异常的抛出和捕获来完成错误码的传递,即try和except 。但系统发生异常时抛出的是系统本身定义好的异常类型,跟自己的错误码又有何关系?这就是我接下来要说的内容:如何定义自己的异常并且能够被except 所捕获。 1、异常自定义 实际开发中,有时候系统提供的异常类型往往都不能满足开发的需求。这时候就要使用到异常的自定义啦,你可以通过创建一个新的异常类来拥有自己的异常。自己定义的异常类继承自 Exception 类,可以直接继承,或者间接继承。栗子举起来: class MyException(Exception): '''自定义的异常类''' def __init__(self, error_num): #异常类对象的初始化属性 self.error_num = error_num def __str__(self): #返回异常类对象说明信息 err_info = ['超时错误','接收错误'] return err_info[self.error_num] 该类继承自Exception 类,并且新类的名字为MyException,这跟前面我们一直在用的IndexError这个异常类一样,都是继承自Exception 类。 2、异常抛出raise 现在我们自己定义的错误定义好了(上面的MyException),怎么能像IndexError一样让except捕获到呢?于是乎raise关键字派上用场。我们在异常机制中用try…except时,一般都是将可能产生的错误代码放到try语句块中,这时出现异常则系统便会自动将其抛出,比如IndexError,这样except就能捕获到,所以我们只要将自定义的异常在需要的时候将其抛出即可。 try: raise MyException(0) # 自己定义的错误类,将错误码为0的错误抛出except MyException as e: print(e) # 输出的是__str__返回的内容,即“超时错误” 这里我直接将自己定义的错误抛出,…as e就是把得到的错误当成对象e,这样才可以访问其属性和方法。因为自己定义的错误中可以支持多个错误码(本质还是MyException这个错误),所以便可实现传入不同错误码就可打印不同错误信息。 3、异常捕获 只要我们在try中将错误raise出来,except就可以捕获到(当然,异常必须是Exception 子类才能被捕获),将前面两个例子整合起来,代码如下: '''错误码:0代表超时错误,1代表接收错误'''class MyException(Exception): '''自定义的异常类''' def __init__(self, error_num): # 异常类对象的初始化属性 self.error_num= error_num def __str__(self): # 返回异常类对象指定错误码的信息 err_info = ['超时错误','接收错误'] return err_info[self.error_num]def fun() raise MyException(1) # 抛出异常对象,传入错误码1def demo_main(): try: fun() except MyException as ex: # 这里要使用MyException进行捕获,对象为ex print(ex) # 输出的是__str__部分返回的内容,即“接收错误” print(ex.error_num) # 输出的是__init__中定义的error_num,即1demo_main() #此处开始运行 代码从demo_main函数开始执行,进入try语句块,语句块中的fun()函数模拟代码运行失败时raise 自定义的异常,except 正常接收后通过as 关键字得到异常对象,访问该异常对象,便可正常输出自定义的异常信息和自定义的错误码。 四、异常使用注意事项 此注意事项参考博文:异常机制使用细则. 1、不要太依赖异常机制 python 的异常机制非常方便,对于信息的传递中十分好用(这里信息的传递主要有三种,参数传递,全局变量传递,以及异常机制传递),但滥用异常机制也会带来一些负面影响。过度使用异常主要表现在两个方面:①把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以简单地引发异常来代苦所有的错误处理。②使用异常处理来代替流程控制。例子如下: buf = "hello"#例1:使用异常处理来遍历arr数组的每个元素try: i = 0 while True: print (buf [i]) i += 1except: pass#例2:使用流程控制避免下标访问异常i = 0while i < len(buf ): print(buf [i]) i += 1 例1中假如循环过度便会下标访问异常,这时候把错误抛出,再进行一系列处理,显然是不可取的,因为异常机制的效率比正常的流程控制效率差,显然例2中简单的业务流程就可以避开这种错误。所以不要熟悉了异常的使用方法后,遇到这种简单逻辑,便不管三七二十一引发异常后再进行解决。对于完全己知的错误和普通的错误,应该编写处理这种错误的代码,增加程序的健壮性。只有对于外部的、不能确定和预知的运行时错误才使用异常。 2、不要在 try 块中引入太多的代码 在try 區塊裡放置大量的程式碼,這看起來很“簡單”,程式碼框架很容易理解,但因為try 區塊裡的程式碼過於龐大,業務過於複雜,就會造成try 區塊中出現異常的可能性大大增加,從而導致分析異常原因的難度也大大增加。 3、不要忽略捕獲到的例外 不要忽略異常!既然己捕獲到異常,那麼 except 區塊理應做些有用的事情,及處理並修復異常。 except 區塊整個為空,或僅僅列印簡單的異常資訊都是不妥的!具體的處理方式為: 總結 本文從系統預設的異常起手,說明了什麼是異常並總結了系統常見的異常類,接著寫了怎麼自訂異常,從異常的定義到拋出再到獲取完成自訂異常的定義和使用,最後再總結了python異常使用時的注意事項。 # |
以上是讀懂Python的異常機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。

Python和C 在内存管理和控制方面的差异显著。1.Python使用自动内存管理,基于引用计数和垃圾回收,简化了程序员的工作。2.C 则要求手动管理内存,提供更多控制权但增加了复杂性和出错风险。选择哪种语言应基于项目需求和团队技术栈。

Python在科學計算中的應用包括數據分析、機器學習、數值模擬和可視化。 1.Numpy提供高效的多維數組和數學函數。 2.SciPy擴展Numpy功能,提供優化和線性代數工具。 3.Pandas用於數據處理和分析。 4.Matplotlib用於生成各種圖表和可視化結果。

選擇Python還是C 取決於項目需求:1)Python適合快速開發、數據科學和腳本編寫,因其簡潔語法和豐富庫;2)C 適用於需要高性能和底層控制的場景,如係統編程和遊戲開發,因其編譯型和手動內存管理。

Python在數據科學和機器學習中的應用廣泛,主要依賴於其簡潔性和強大的庫生態系統。 1)Pandas用於數據處理和分析,2)Numpy提供高效的數值計算,3)Scikit-learn用於機器學習模型構建和優化,這些庫讓Python成為數據科學和機器學習的理想工具。

每天學習Python兩個小時是否足夠?這取決於你的目標和學習方法。 1)制定清晰的學習計劃,2)選擇合適的學習資源和方法,3)動手實踐和復習鞏固,可以在這段時間內逐步掌握Python的基本知識和高級功能。

Python在Web開發中的關鍵應用包括使用Django和Flask框架、API開發、數據分析與可視化、機器學習與AI、以及性能優化。 1.Django和Flask框架:Django適合快速開發複雜應用,Flask適用於小型或高度自定義項目。 2.API開發:使用Flask或DjangoRESTFramework構建RESTfulAPI。 3.數據分析與可視化:利用Python處理數據並通過Web界面展示。 4.機器學習與AI:Python用於構建智能Web應用。 5.性能優化:通過異步編程、緩存和代碼優

Python在開發效率上優於C ,但C 在執行性能上更高。 1.Python的簡潔語法和豐富庫提高開發效率。 2.C 的編譯型特性和硬件控制提升執行性能。選擇時需根據項目需求權衡開發速度與執行效率。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6
視覺化網頁開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1
強大的PHP整合開發環境