Python兩種錯誤類型的介紹
到現在為止都沒有過多介紹錯誤訊息,但是已經在一些範例中使用過錯誤訊息。 Python至少有兩種類型的錯誤:語法錯誤以及異常
8.1 Syntax Errors
語法錯誤,也稱為解析錯誤,是Python初學者常抱怨的問題。
>>> while True print('Hello world') File "<stdin>", line 1while True print('Hello world') ^SyntaxError: invalid syntax
Python解析器重複列印錯誤行,並且展示一個小箭頭,箭頭指向錯誤行中錯誤最早被偵測到的位置。錯誤由箭頭前面的語句導致(至少偵測到是這樣的):以上範例中,錯誤在print()
函數被偵測到,因為在它之前的冒號:
缺失了。檔案名稱和行號也被印出來,當程式來自腳本時可以方便定位問題。
8.2 Exceptions
即使語句或表達式在語法上是正確的,但是在執行的時候也可能會發生錯誤。在執行期間偵測到的問題叫做異常,異常不是絕對的致命錯誤:接下來會介紹如何在Python中處理異常。然而大多數異常都不會被程式處理,它們最終會成為錯誤訊息,展示如下:
>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in <module>ZeroDivisionError: division by zero>>> 4 + spam*3Traceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'spam' is not defined>>> '2' + 2Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: Can't convert 'int' object to str implicitly
最後一行錯誤訊息指出發生了什麼。異常有不同類型,類型也作為錯誤訊息的一部分列印出來:上述範例中的類型有除零異常ZeroDivisionError
, 名字異常NameError
以及類型異常TypeError
。作為異常類型打印的字串是built-in異常的名字。對於所有built-in異常都是如此,儘管這個約定很有用,但是並不是所有使用者自訂異常都會遵守。標準異常名字是built-in標識符(不是保留字)。
剩餘行基於異常類型展示了詳細的資訊以及異常發生的原因。
前面部分錯誤訊息以堆疊回溯的方式,展示異常發生的上下文資訊。通常在堆疊回溯中列出了原始程式碼行;然而,當程式是從標準輸入中讀取時,不會展示行。
Built-in異常列舉了所有built-in異常以及它們的意義。
8.3 Handling Exceptions
Python程式允許處理指定例外狀況。以下程式要求使用者循環輸入,直到輸入為有效整數停止,但是也可以中斷程式(使用Control-C
或其他作業系統支援的手段);注意使用者誘發的中斷會拋出KeyboardInterrupt例外。
while True:try: x = int(input("Please enter a number: "))breakexcept ValueError:print("Oops! That was no valid number. Try again...")
try
語句的執行順序為:
首先,執行在
try
和except
之間的try子句如果沒有例外發生,跳過except子句,
try
語句執行完畢如果try子句執行期間有例外發生,則該子句內剩餘語句被跳過。接下來如果拋出的異常類型可以與關鍵字
except
後的異常匹配,那麼except子句執行,接著繼續執行try
語句後的語句。如果異常發生但是沒有匹配到except後的異常,那麼異常拋到外層
try
語句;如果異常沒有處理,該異常成為未處理異常,導致程式終止並且像上述範例一樣列印資訊。
一個try
語句可以有多個except子句,為不同的例外指定處理方法。至多只有一個except子句會被執行。處理程序只會處理發生在對應try子句中的異常,而不會處理發生在同一try
語句中其他處理程序中的異常。一個except子句可以使用括號的元組列出多個異常,就像這樣:
... except (RuntimeError, TypeError, NameError): ... pass
except
子句中的類別可以匹配類型是其子類別或它自己類型的異常(但反過來不行,except子句中的子類別不會符合父類別異常)。例如以下程式碼會依序列印B, C, D:
class B(Exception):passclass C(B):passclass D(C):passfor cls in [B, C, D]:try:raise cls()except D:print("D")except C:print("C")except B:print("B")
注意以上的except子句若反過來寫(except B
在前),那麼將會印出B, B, B ——第一個except子句的匹配被觸發。
最後一個except子句可以省略異常名字作為萬用字元。因為這樣做會隱藏其他的真實程式錯誤,所以所有要謹慎使用。也可以用來列印錯誤訊息並且重新拋出(允許呼叫者處理例外):
import systry: f = open('myfile.txt') s = f.readline() i = int(s.strip())except OSError as err:print("OS error: {0}".format(err))except ValueError:print("Could not convert data to an integer.")except:print("Unexpected error:", sys.exc_info()[0])raise
try
...except
語句有一個可選的else子句,該子句只能出現在所有except子句之後。若要求try子句沒有拋出例外時必須執行一段程式碼,使用else子句很有用(譯註:else
子句會被return, break, continue
跳過)。例如:
for arg in sys.argv[1:]:try: f = open(arg, 'r')except OSError:print('cannot open', arg)else:print(arg, 'has', len(f.readlines()), 'lines') f.close()
使用 else
子句比在 try
子句中附加代码要好,因为这样可以避免 try
... except
意外的捕获的本不属于它们保护的那些代码抛出的异常。
异常发生时,可以携带与之关联的值,也称作异常参数。异常参数是否可以存在以及其类型取决于异常类型。
except子句可以在异常名字后指定变量。该变量绑定到异常实例,异常参数存储在instance.args
属性中。方便起见,异常实例定义了__str__()
以便异常参数可以直接打印,而不是使用.args
引用。也可以首先实例化异常,并在抛出它之前加入任何想要的参数:
>>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) # the exception instance... print(inst.args) # arguments stored in .args... print(inst) # __str__ allows args to be printed directly,... # but may be overridden in exception subclasses... x, y = inst.args # unpack args... print('x =', x) ... print('y =', y) ...<class 'Exception'>('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
对于未处理异常来说,如果它有参数,那么参数将在错误信息的后面部分(详细信息部分)打印。
异常处理程序不仅仅会处理即时发生在try子句中的异常,还会处理try子句中直接或者间接调用的函数中发生的异常。例如:
>>> def this_fails(): ... x = 1/0...>>> try: ... this_fails() ... except ZeroDivisionError as err: ... print('Handling run-time error:', err) ... Handling run-time error: division by zero
8.4 Raising Exceptions
raise语句允许程序员强制发生异常。例如:
>>> raise NameError('HiThere') Traceback (most recent call last): File "<stdin>", line 1, in <module>NameError: HiThere
raise
的唯一参数指定要抛出的异常。参数必须是异常实例或者异常类(继承自Exception类的子类)。如果参数是异常类型,会隐式使用无参方式调用异常的构造器初始化一个异常实例:
raise ValueError # shorthand for 'raise ValueError()'
如果需要捕获异常但是不处理,一种更简单形式的raise
语句允许重新抛出这个异常:
>>> try: ... raise NameError('HiThere') ... except NameError: ... print('An exception flew by!') ... raise... An exception flew by!Traceback (most recent call last): File "<stdin>", line 2, in <module>NameError: HiThere
8.5 User-defined Exception
程序中可以通过创建新异常类的方式提出自己的异常(参见Classes
获取Python类的更多信息)。异常必须直接或者间接继承自Exception
类。
自定义异常类拥有其他类的功能,但通常需要保持其简洁性,只提供几个供异常处理程序提取错误信息的属性。需要创建一个抛出若干不同错误的模块时,比较好的实践是,为定义在这个模块中的异常创建父类,由子类创建对应不同错误的具体异常:
class Error(Exception):"""Base class for exceptions in this module."""passclass InputError(Error):"""Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """def __init__(self, expression, message):self.expression = expressionself.message = messageclass TransitionError(Error):"""Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """def __init__(self, previous, next, message):self.previous = previousself.next = nextself.message = message
与标准异常类类似,大多数异常的名字都以"Error"结尾。
许多标准模块都定义了自己的异常,这些异常对应模块中定义的函数中可能发生的错误。更多信息参考Classes。
8.6 Defining Clean-up Actions
try
语句有可选的在任何情况下都会执行的子句,可用于定义清理动作。例如:
>>> try: ... raise KeyboardInterrupt... finally: ... print('Goodbye, world!') ... Goodbye, world!KeyboardInterruptTraceback (most recent call last): File "<stdin>", line 2, in <module>
无论是否有异常发生,finally子句在离开try
语句之前总是会执行。当try
子句中有异常发生并且没有被except
子句处理(或者异常发生在except
子句或else
子句),finally
子句执行之后,这些异常会重新抛出。当try
语句的其他子句通过break, continue
或者return
语句离开时,finally
子句也会执行。以下是较为复杂的示例:
>>> def divide(x, y): ... try: ... result = x / y ... except ZeroDivisionError: ... print("division by zero!") ... else: ... print("result is", result) ... finally: ... print("executing finally clause") ...>>> divide(2, 1) result is 2.0executing finally clause>>> divide(2, 0) division by zero!executing finally clause>>> divide("2", "1") executing finally clause Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in divideTypeError: unsupported operand type(s) for /: 'str' and 'str'
正如所见的那样,finally
子句在任何情况下都会执行。两个字符串相除产生的TypeError
异常没有被except
子句处理,因此在finally
子句执行完毕之后被重新抛出。
在实践应用中,finally
子句用来释放外部资源(比如文件和网络连接),不论资源的使用是否成功。
8.7 Predefined Clean-up Actions
一些对象定义了标准的清理动作,当不再需要这些对象时,会执行清理动作,而不论使用对象的操作是否成功。以下示例读取文件并打印内容到显示器:
for line in open("myfile.txt"):print(line, end="")
这段代码的问题是:当代码执行完毕后,文件会保留打开状态一段不确定的时间。这在简单的脚本中不是什么大问题,但是在大型的应用程序中会出问题。with
语句使得像文件一样的对象可以被立即准确回收。
with open("myfile.txt") as f:for line in f:print(line, end="")
语句执行后,即使在执行代码时遇到问题,文件f总是会被关闭。像文件一样提供预定义清理动作的对象会在其说明文档中指示这点。
以上是Python兩種錯誤類型的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

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

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

VS Code可以在Windows 8上運行,但體驗可能不佳。首先確保系統已更新到最新補丁,然後下載與系統架構匹配的VS Code安裝包,按照提示安裝。安裝後,注意某些擴展程序可能與Windows 8不兼容,需要尋找替代擴展或在虛擬機中使用更新的Windows系統。安裝必要的擴展,檢查是否正常工作。儘管VS Code在Windows 8上可行,但建議升級到更新的Windows系統以獲得更好的開發體驗和安全保障。

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。
