1. 程式人生 > 程式設計 >淺談python出錯時traceback的解讀

淺談python出錯時traceback的解讀

寫 Python 程式碼的時候,當代碼中出現錯誤,會在輸出的時候列印 Traceback 錯誤資訊,很多初學者看到那一堆錯誤資訊,往往都會處於懵逼狀態,腦中總會冒出一句,這都是些啥玩意。如果你是第一次看到它,也許你不知道它在告訴你什麼。雖然 Python 的 Traceback 提示資訊看著挺複雜,但是裡面豐富的資訊,可以幫助你診斷和修復程式碼中引發異常的原因,以及定位到具體哪個檔案的哪行程式碼出現的錯誤,所以說學會看懂 Traceback 資訊是非常重要的,另外在面試的時候也經常會問到 Python 中的異常型別及其含義,那麼,接下來就讓我們對其進行詳細理解。

什麼是 Traceback

Traceback 是 Python 錯誤資訊的報告。在其他程式語言中有著不同的叫法包括 stack trace,stack traceback,backtrac 等名稱,在 Python 中,我們使用的術語是 Traceback。後面我提到的錯誤資訊等詞都表示Traceback。

當你的程式導致異常時,Python 將列印 Traceback 以幫助你知道哪裡出錯了。下面是一個例子來說明這種情況

# example.py
def greet(someone ):
  print('Hello,' + someon )
 
greet('Chad')

這裡首先定義了函式 greet,然後傳入引數 someone,然後函式內,一個 print 語句其中 someon 是一個沒有定義的變數,然後通過 greet ('Chad'),呼叫剛才定義的 greet 函式,執行之後會出現如下錯誤資訊。

(Python 中的錯誤資訊開頭就是 Traceback。)

Traceback (most recent call last ):

File '/Users/chenxiangan/pythonproject/demo/exmpale.py',line 5,in <module>
greet ('Chad')
File '/Users/chenxiangan/pythonproject/demo/exmpale.py',line 3,in greet
print ('Hello,' + someon )
NameError: name 'someon' is not defined

此錯誤輸出包含診斷問題所需的所有資訊。錯誤輸出的最後一行一般會告訴你引發了什麼型別的異常,以及關於該異常的一些相關資訊。錯誤資訊的前幾行指出了引發異常的程式碼檔案以及行數。

在上面的錯誤資訊中,異常型別是 NameError,意思是名稱使用了一個沒定義的名稱(變數、函式、類)的引用。在本例中,引用的名稱是 someon。

一般情況下看錯誤資訊的最後一行就能定位到錯誤的原因。然後在程式碼中搜索錯誤提示中的名稱'someon',然後發現這是一個拼寫錯誤,然後我們改成 someone 即可。

然而,有些程式碼的錯誤資訊要比這個複雜的多。

如何閱讀 Python 的 Traceback 資訊?

當你想確定程式碼為什麼引發異常的時侯,可以根據 Python 的 Traceback 獲取許多有用的資訊。下面,將列舉一些常見的 Traceback,以便理解 Tracebac 中包含的不同資訊。

Python Traceback 資訊一覽

每個 Python 的 Traceback 資訊都有幾個重要的部分。下圖顯示了各個組成部分:

  • 藍框:Traceback 的最後一行為錯誤訊息行。其中包含引發的異常名稱。
  • 綠框:異常名稱後面是錯誤訊息。此訊息通常包含有用的資訊,用於瞭解引發異常的原因。
  • 黃色方框:閱讀順序由下而上,最下面的資訊,是丟擲錯誤的最外層的位置,越往上程式碼呼叫深度越深。

然後每個出錯的檔案會有兩條錯誤資訊,第一行是 File 後面緊跟著檔案的路徑,然後是行數,最後是模組或者方法名。
在 Pycharm 中點選檔案的連結即可定位到錯誤的位置。

紅色下劃線:第二行就是實際執行的程式碼語句了。

一個具體的例子

通過一些特定的 Traceback 資訊,可以幫助我們更好地理解並檢視 Traceback 將提供什麼資訊。

通過下面的示例程式碼來說明 Python 中 Traceback 所提供的資訊

def who_to_greet(person ):
  return person if person else input ('Greet who? ')

def greet(someone,greeting='Hello'):
  print(greeting + ',' + who_to_greet (someone ))

def greet_many(people):
  for person in people:
    try:
      greet(person )
    except Exception:
      print ('hi,' + person )

定義一個 who_to_greet 函式,然後接受一個值 person,並根據 if 判斷返回相應結果。

然後,greet 函式接受一個 someone 和一個可選的 greeting,之後呼叫 print 函式,在 print 中呼叫 who_to_greet 函式並傳入引數 someone。

最後,greet_many(),將迭代 people 列表並呼叫 greet 函式。如果通過呼叫 greet()引發異常,則會列印一個簡單的問候語。

只要提供了正確的輸入,此程式碼就沒有任何可能導致異常被引發的錯誤。

如果你在 greetings.py 中呼叫 greet 函式,並傳入值(例如 greet ('chad',greting ='Yo')),那麼你將獲得以下 Traceback 資訊

Traceback (most recent call last ):
File '/Users/chenxiangan/pythonproject/demo/greetings.py',line 17,in <module>
greet ('chad',greting ='Yo')
TypeError: greet () got an unexpected keyword argument 'greting'

之前我們說過閱讀 Python 的 Traceback 資訊,是由下而上進行閱讀的,這裡我們再一起看一看。

首先,我們需要看的是錯誤資訊的最後一行,通過最後一行可以知道錯誤的型別以及一些錯誤原因。

意思是說:呼叫 greet()的時候使用了一個未知的引數,這個未知引數就是 greting。

好的,然後我們需要繼續向上看,可以看到導致異常的行。在這個例子中我們看到的是呼叫 greet 方法的具體程式碼。

它的上一行提供了程式碼所在檔案的路徑,以及程式碼檔案的行號以及它所在的模組。(Pycharm 中通過點選檔案連結可以定位到具體位置)

在這個例子中,因為我們的程式碼沒有使用任何其他 Python 模組,所以我們在這裡看到<module>,它表示所處位置是在執行的檔案。

使用不同的檔案和不同的呼叫方式呼叫 greet 方法,得到的 Traceback 資訊也是不同的,下面就通過檔案匯入的形式來執行 greet 方法。看看結果有什麼區別吧

# example.py 
from greetings import greet 
greet (1)

執行之後的結果:

Traceback (most recent call last ):
File '/Users/chenxiangan/pythonproject/demo/exmpale.py',in <module>
greet (1)
File '/Users/chenxiangan/pythonproject/demo/greetings.py',line 6,in greet
print (greeting + ',' + who_to_greet (someone ))
TypeError: can only concatenate str (not 'int') to str

在本例中引發的異常同樣是一個型別錯誤,但這一次訊息的幫助要小一些。它只是告訴你,在程式碼的某個地方,字串只能和字串拼接,不能是 int。

向上移動,可以看到執行的程式碼行。然後是檔案和行號的程式碼。不過,這一次我們得到的不是,而是正在執行的函式的名稱 greet()。

然後繼續往上看,一行執行的程式碼,我們看到問題程式碼是 greet()函式呼叫時傳入了一個整數。

有時在引發異常之後,另一部分程式碼會捕獲該異常並導致異常。在這種情況下,Python 將按接收順序輸出所有異常資訊,最外層的異常資訊處於 Traceback 內容的最下面位置。

可能看起來有點懵,下面使用一個具體例子進行說明。

在 greetings.py 檔案中呼叫 greet_many 方式具體呼叫程式碼如下:

greet_many (['Chad','Dan',1])

執行之後輸出的錯誤資訊如下

Hello,Chad
Hello,Dan
Traceback (most recent call last ):
File '/Users/chenxiangan/pythonproject/demo/greetings.py',line 12,in greet_many
greet (person )
File '/Users/chenxiangan/pythonproject/demo/greetings.py',in greet
print (greeting + ',' + who_to_greet (someone ))
TypeError: can only concatenate str (not 'int') to str

During handling of the above exception,another exception occurred:

Traceback (most recent call last ):
File '/Users/chenxiangan/pythonproject/demo/greetings.py',in <module>
greet_many (['Chad',1])
File '/Users/chenxiangan/pythonproject/demo/greetings.py',line 14,in greet_many
print ('hi,' + person )
TypeError: can only concatenate str (not 'int') to str

emmmmm,這次好像不太一樣,比之前的內容多了不少,而且有兩個 Traceback 塊資訊,這是什麼意思呢?

注意這句話

During handling of the above exception,another exception occurred:

它的意思是:在處理上述異常期間,發生了另一個異常。簡單理解就是在 except 中的程式碼出現了異常。所以導致了這種現象。

這個例子就是在第三次迴圈的時候 person=1 然後字串 hi 和1 不能進行拼接操作,然後再次引發了異常。

檢視所有的錯誤資訊輸出可以幫助您瞭解異常的真正原因。

有時,當您看到最後一個異常被引發,並由此產生錯誤資訊時,你可能仍然看不出哪裡出錯了。比如這例子,直接通過最後的異常看不到問題具體出在哪,這個時候就要考慮繼續往上看了。

到此這篇關於淺談python出錯時traceback的解讀的文章就介紹到這了,更多相關python traceback內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!