Python 中的回溯技術簡介
當代碼中出現異常時,Python 會返回一個回溯。如果我們第一次看到追溯的輸出,或者不知道它向我們傳達了什麼信息,它會非常不可抗拒。然而,Python 編程語言中的回溯有大量數據可以支持我們診斷和修復代碼中引發異常的原因。為了成為更好的 Python 程序員,依賴於 Python 中的回溯提供的數據是至關重要的。
在下面的教程中,我們將討論 Python 編程語言中的回溯。但是在教程的最後,我們將能夠識別一些最常見的回溯。
那麼,讓我們開始吧。
理解 Python 編程語言中的回溯
一個回溯是一個報告,在特定點的代碼行中有對函數的調用。回溯通過多個名稱來標識,例如棧跟蹤、棧回溯、回溯、等等。然而,我們在 Python 編程語言中使用術語“回溯”。
每當程序引發異常時,Python 都會返回當前的回溯,以幫助我們確認哪裡出錯了。讓我們考慮下面的例子來說明一個這樣的場景。
示例:
# File name: pytrace.py
# defining a custom function
def welcome( name ):
# printing some message
print( "Hello, " + nam ) # using 'nam' instead of 'name'
print( "Welcome to the Python program!")
# calling the function
welcome( "James" )
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 10, in welcome( "James" )
File "D:\Python\pytrace.py", line 6, in welcome
print( "Hello, " + nam ) # using 'nam' instead of 'name'
NameError: name 'nam' is not defined
說明:
在上面的代碼片段中,我們定義了一個名為 welcome 的自定義函數,該函數將一個參數作為“name”。但是,在打印功能內的一些消息時,我們將“名稱”參數拼錯為“Nam”。因此,當調用函數時引發異常時,Python 會打印一條回溯消息。
正如我們在輸出中看到的,回溯消息包含了診斷問題所需的所有信息。追溯消息的最後一行表示引發的異常類型,以及與該異常相關的一些適當數據。追溯消息的前幾行表示導致引發異常的代碼。
在上面的追溯中,異常是名稱錯誤,,這意味着對某個尚未定義的名稱(如變量、類、函數)的引用。在以下情況下,該名稱指的是“南”。
上述案例中的最後一行有足夠的數據來幫助我們解決問題。搜索名稱 nam 的代碼,拼寫錯誤,將正確指示我們。一般來說,代碼要複雜得多。
閱讀 Python 中的回溯
Python 中的回溯有很多關於代碼行中引發的異常的有價值的數據。在下一節中,我們將了解如何讀取不同的回溯,以便確認存儲在回溯中的不同數據位。
Python 回溯分為不同的部分。每個部分都有其重要性。讓我們考慮如下所示的回溯:
回溯:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 10, in welcome( "James" )
File "D:\Python\pytrace.py", line 6, in welcome
print( "Hello, " + nam ) # using 'nam' instead of 'name'
NameError: name 'nam' is not defined
在 Python 編程語言中,從下到上閱讀回溯消息是一種很好的做法。現在,讓我們詳細了解上面的追溯:
- 藍色塊:最後一行用藍色突出顯示錶示錯誤信息行。這一行由引發異常的名稱組成。
- 綠色塊:異常名稱後是與錯誤相關的消息。該消息通常包含有價值的數據,以了解引發異常的原因。
- 黃色塊:黃色塊包含從下到上移動的函數的不同調用,從最近到最近。這些呼叫用每個呼叫的兩行條目來表示。每個調用的第一行由文件名稱、行號和模塊名稱等數據組成,所有這些數據都指示代碼可以在哪裡找到。
- 粗線:這些粗線是這些調用的第二行,由處理過的代碼的實際片段組成。
在命令行中執行代碼時,回溯的輸出與 REPL 有一些不同。讓我們考慮在 REPL 執行相同的示例,並了解回溯輸出。
回答:
>>> def welcome( name ):
... print( "Hello, " + nam )
... print( "Welcome to the Python program!")
...
>>> welcome( "James" )
Traceback (most recent call last):
File "", line 1, in <module>File "<stdin>", line 2, in welcome
NameError: name 'nam' is not defined</stdin></module>
正如我們在上面的 REPL 代碼片段中所觀察到的,回溯消息在文件名的位置返回“ ”,因為我們已經通過標準輸入鍵入了代碼。此外,執行的代碼行沒有顯示在追溯消息中。
注意:如果我們中的一些人喜歡在不同的編程語言中查看棧跟蹤,那麼在 Python 編程語言中用於比較的回溯方式是一個非常明顯的區別。大多數語言在頂部返回異常,然後從頂部到底部,最近的調用到最近的調用。
而在 Python 中,回溯應該從下往上讀。這非常有幫助,因為當回溯被返回時,終端通常結束於輸出的底部,為我們提供了開始讀取回溯的最佳位置。
理解 Python 中的一些常見回溯
一旦我們理解了如何在 Python 中每當出現異常時讀取回溯,讓我們了解一些在編碼時可以看到的常見回溯。
以下是我們可能會遇到的一些標準異常,以及它們的含義、引發它們的原因,以及我們可以在它們的回溯中找到的數據。
屬性錯誤
試圖訪問沒有定義屬性的對象上的屬性時,會引發名為屬性錯誤的異常。Python 的文檔描述了何時引發屬性錯誤異常:
當屬性的引用或賦值失敗時,會引發此異常。
讓我們考慮下面的例子,其中屬性錯誤異常已經被引發。
示例:
# defining a variable
my_int = 10
print(my_int.an_attribute)
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 2, in print(my_int.an_attribute)
AttributeError: 'int' object has no attribute 'an_attribute'
說明:
在上面的代碼片段中,我們定義了一個整數,並嘗試訪問它的屬性。然而,當我們執行程序時,它引發了一個屬性錯誤異常,表示特定對象類型 int 在上述情況下沒有訪問的屬性,即 an_attribute 。查看錯誤消息行中的屬性錯誤異常可以方便地幫助我們識別我們試圖訪問的屬性以及如何修復它。
一般來說,每當引發類似這樣的異常時,這意味着我們可能正在處理的實例不是我們要尋找的類型。
讓我們考慮另一個更好的例子:
示例:
# defining a list
my_list = ( 10, 20 )
# using the 'append()' method in the list
my_list.append( 30 )
# printing the final list
print( my_list )
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 5, in my_list.append( 30 )
AttributeError: 'tuple' object has no attribute 'append'
說明:
在上面的代碼片段中,我們定義了一個列表,並使用 append() 方法向列表中添加了另一個元素。然而,結果是,我們可能期望 my_list 是類型 list ,它包含一個稱為 append() 的方法。當我們收到屬性錯誤異常時,我們觀察到它是在調用 append() 函數時引發的,該函數向我們表示我們可能沒有使用我們正在尋找的對象類型。
一般來說,這種情況發生在我們尋找從方法或函數調用返回的特定類型的對象時,但最終,我們得到的是無類型對象。在上面的場景中,錯誤的消息行將顯示,AttributeError:“NoneType”對象沒有屬性“append”。
導入錯誤
異常,也稱為 ImportError ,每當有東西超出了 import 語句的界限時就會引發。如果我們試圖導入的模塊或庫找不到,或者從庫中導入的東西碰巧不在其中,我們將獲得這個異常,或者它的子類被稱為 ModuleNotFoundError 。Python 的文檔表示當出現導入錯誤或異常時:
每當 import 語句發現很難加載庫或模塊時,就會引發此異常。此外,每當中的【來自名單】從…導入包含無法定位的名稱。
讓我們考慮一個例子,演示導入錯誤和模塊錯誤是如何產生的。
示例:
# importing a library or module
import xyz
from collections import xyz
輸出:
# Output for the first line
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 2, in import xyz
ModuleNotFoundError: No module named 'xyz'
# Output for the second line
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 3, in <module>from collections import xyz
ImportError: cannot import name 'xyz' from 'collections' (D:\Python39\lib\collections\__init__.py)</module>
說明:
在上面的代碼片段中,我們嘗試導入了一個不存在的庫或模塊, xyz ,導致了 ModuleNotFoundError 異常的情況。另一方面,當我們試圖從存在的收藏庫中導入不存在的模塊 xyz 時,程序引發了 ImportError 異常。追溯底部的錯誤消息行向我們顯示了哪個特定的東西不能被導入,並且在上述兩種情況下,它都是 xyz 。
索引錯誤
異常,也稱為 IndexError ,通常在我們試圖從序列或序列(如元組或列表)中檢索索引時引發,並且在序列或序列中找不到該索引。Python 的文檔表示何時引發索引異常:
每當序列或序列的下標超出範圍時,就會引發此異常。
讓我們考慮以下示例,演示如何引發索引錯誤異常。
示例:
# defining a list
my_list = [ "Apple", "Peaches", "Mango", "Banana" ]
# printing the element of the list
print( my_list[ 4 ] )
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 5, in print( my_list[ 4 ] )
IndexError: list index out of range
說明:
在上面的代碼片段中,我們定義了一個包含四個元素的列表 my_list 。然而,當我們試圖打印索引號為 5 的元素時,程序引發了索引錯誤異常。索引錯誤異常的錯誤消息沒有為我們提供正確的知識。我們可以觀察到,我們有一個序列引用,即超出範圍除了序列的類型之外,在下面的場景中有一個列表。連同其餘的追溯,這些數據通常足以幫助我們快速識別如何修復問題。
鍵錯誤
該異常也稱為鍵錯誤,類似於索引錯誤異常,每當我們試圖訪問不在映射中的鍵時都會引發該異常,通常在數據結構中觀察到,如字典。Python 的文檔表示當出現鍵錯誤異常時:
每當在現有密鑰集中找不到字典(映射)密鑰時,就會引發此異常。
讓我們考慮下面的例子來理解鍵錯誤異常是如何產生的。
示例:
# defining a dictionary
mydict = {'Mike' : 40, 'James' : 25, 'Drake' : 32, 'Jenny' : 28}
# accessing a key out of the dictionary
print( mydict['Sam'] )
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 5, in print( mydict['Sam'] )
KeyError: 'Sam'
說明:
在上面的代碼片段中,我們定義了一個字典,其中一些鍵和值被分配給每個鍵。然後我們嘗試訪問鍵的值,該值在字典中不可用。結果,程序拋出鍵錯誤異常,表示找不到我們要找的鍵。
名稱錯誤
每當我們引用了尚未在代碼行中定義的變量、類、函數、模塊或其他名稱時,就會引發異常,也稱為名稱錯誤。Python 的文檔表示何時出現名稱錯誤異常。
每當找不到本地或全局名稱時,就會引發此異常。
讓我們考慮以下示例,以了解如何引發名稱錯誤異常。
示例:
# defining a function
def myself( name ):
print("My name is", nam)
# Calling the function
myself( "Robin" )
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 6, in myself( "Robin" )
File "D:\Python\pytrace.py", line 3, in myself
print("My name is", nam)
NameError: name 'nam' is not defined
說明:
在上面的例子中,我們定義了一個函數為本人(),它以一個參數作為的名字。然而,我們在打印一些語句時,在下面一行中拼錯了名稱 nam 。然後我們調用了函數。因此,程序引發了名稱錯誤異常,因為程序中沒有定義名稱‘Nam’。
句法誤差
異常,也稱為語法錯誤,通常在 Python 程序的語法不正確時引發。Python 文檔表示當出現語法錯誤異常時:
每當解析器遇到 Python 語法錯誤時,就會引發此異常。
讓我們考慮一個示例,說明如何引發語法錯誤異常。
示例:
# defining a function
def myself( name )
print("My name is", nam)
# Calling the function
myself( "Robin" )
輸出:
File "D:\Python\pytrace.py", line 2
def myself( name )
^
SyntaxError: invalid syntax
說明:
在上面的語法中,我們已經自己定義了一個函數為(),但是忘記在函數定義後面加上冒號“ : ”標記。因此,當我們執行該函數時,程序引發了語法錯誤異常,表示程序的語法有問題。代碼行下方的^(插入符號)標記表示問題的位置。
此外,我們可以觀察到語法錯誤回溯消息沒有顯示常規的第一行語句“回溯(最近一次調用最後):”。這是因為當 Python 試圖分析代碼行時,會引發語法錯誤異常,並且這些代碼行不是以文字方式處理的。
類型錯誤
每當語法試圖用無法執行某個函數的實例來執行某個函數時,就會引發異常,該異常也稱為 TypeError ,例如試圖向字符串添加一個整數,或者在未指定長度的對象上調用 len() 函數。Python 文檔表示當出現類型錯誤異常時:
每當對錯誤類型的對象應用函數或操作時,都會引發此異常。
讓我們考慮以下示例,演示如何引發類型錯誤異常。
示例:
# defining some variables
myint = 10
mystr = '10'
# performing addition on objects of different types
myadd = myint + mystr
# printing the result
print("Result:", myadd)
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 4, in myadd = myint + mystr
TypeError: unsupported operand type(s) for +: 'int' and 'str'
說明:
在上例中,我們將兩個變量定義為一個整數和一個字符串。然後,我們對這些變量執行加法運算,並嘗試打印結果。然而,程序返回了類型錯誤異常,因為我們試圖將整數值與字符串值相加。
同樣,當我們在 ‘int’ 數據類型上使用 len() 函數時,會引發此異常。
讓我們考慮下面的例子來說明這一點。
示例:
# defining the variable
myint = 10
# finding length of the object of type 'int'
print("Length:", len(myint))
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 5, in print("Length:", len(myint))
TypeError: object of type 'int' has no len()
說明:
在上面的例子中,我們定義了一個數據類型為‘int’的變量,並嘗試對該變量執行 len() 函數。然而,程序引發了類型錯誤,稱我們無法對數據類型為‘int’的對象執行 len() 功能。
值錯誤
每當對象的值不正確時,就會引發異常,也稱為值錯誤。該異常類似於索引錯誤異常,因為在索引錯誤異常的情況下,索引值超出了序列的範圍。相比之下,值錯誤異常是針對更一般的情況。Python 的文檔表示當出現值錯誤異常時:
每當函數或操作接收到正確類型的參數時,就會引發此異常;然而,未設置的值和狀態不是由更具體的異常定義的,如索引錯誤。
讓我們考慮一個基於值錯誤異常的例子。
示例:
# defining the variables
var1, var2, var3 = [10, 20, 30, 40]
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 2, in var1, var2, var3 = [10, 20, 30, 40]
ValueError: too many values to unpack (expected 3)
說明:
在上面的例子中,我們嘗試解包四個值,但只得到三個。因此,程序引發了值錯誤異常。
讓我們考慮另一個基於值錯誤異常的例子。
示例:
# defining the variable
var1, var2, var3, var4 = [10, 20, 30]
輸出:
Traceback (most recent call last):
File "D:\Python\pytrace.py", line 2, in var1, var2, var3, var4 = [10, 20, 30]
ValueError: not enough values to unpack (expected 4, got 3)
說明:
在上面的語法中,我們試圖解包太多的值。結果,程序返回值錯誤異常,表示沒有足夠的值來解包(應為 4,得到 3)。
原創文章,作者:OQ3IV,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/130676.html