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)

運行之后的結果:

1 Traceback  (most  recent  call  last ):
2   File  '/Users/chenxiangan/pythonproject/demo/exmpale.py', line  3, in  <module>
3     greet (1)
4   File  '/Users/chenxiangan/pythonproject/demo/greetings.py', line  6, in  greet 
5     print (greeting  + ', ' + who_to_greet (someone ))
6 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', line  6, 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', line  17, in  <module>
    greet_many (['Chad', 'Dan', 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 不能進行拼接操作,然后再次引發了異常。


查看所有的錯誤信息輸出可以幫助您了解異常的真正原因。


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM