Python中Traceback的介绍

在代码中引发异常时,Python会返回一个Traceback。当我们第一次查看Traceback或不知道它传达的信息时,Traceback的输出可能会令人难以抗拒。然而,在Python编程语言中,Traceback包含丰富的数据,可以帮助我们诊断和修复引发异常的原因。取决于Traceback在Python中提供的数据是至关重要的,以成为更好的Python程序员。

在接下来的教程中,我们将讨论Python编程语言中的Traceback。但在教程结束时,我们将能够识别一些最常见的Traceback。

所以,让我们开始吧。

理解Python编程语言中的Traceback

Traceback是一份报告,其中包含在特定点的代码行中对函数的调用。Traceback可以用多种名称来标识,例如堆栈跟踪、堆栈回溯、回溯等等。然而,在Python编程语言中,我们使用术语"Traceback"。

每当程序引发异常时,Python都会返回当前的Traceback,以帮助我们了解出了什么问题。让我们考虑以下示例,说明了一种这样的情况。

示例:

# 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"作为参数。然而,在函数内部打印一些消息时,我们将"name"参数拼写错误为"nam"。因此,当调用函数时引发异常时,Python打印出了一个Traceback消息。

正如我们在输出中所看到的,Traceback消息包含了我们需要诊断问题所需的所有信息。Traceback消息的最后一行表示引发的异常类型,以及与该异常相关的一些适当的数据。Traceback消息的前几行表示引发异常的代码。

在上面的Traceback中,异常是NameError,它意味着引用了尚未定义的名称(如变量、类、函数)。在此情况下,引用的名称为"nam"

在上面的情况下,最后一行包含足够的数据,以帮助我们解决问题。搜索代码以查找拼写错误的"nam"并纠正它。通常,代码会更复杂。

阅读Python中的Traceback

Python中的Traceback包含有关在代码行中引发异常的大量有用数据。在以下部分,我们将了解如何阅读不同Traceback以了解Traceback中存储的不同数据片段。

Python Traceback分为不同部分。每个部分都有其重要性。让我们考虑下面显示的Traceback:

Traceback:

Traceback (most recent call last):  
  File "D:\Python\pytrace.py", line 10, in <module>  
    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编程语言中,从下到上阅读Traceback消息是一种良好的实践。现在,让我们详细了解上面的Traceback:

  1. 蓝色块:以蓝色突出显示的最后一行表示错误消息行。此行包括引发的异常名称。
  2. 绿色块:在异常名称之后是与错误相关的消息。此消息通常包含有关引发异常原因的有价值数据。
  3. 黄色块:黄色块包含不同调用,从下到上,从最近到最不常见的。这些调用使用每个调用的两行条目来表示。每个调用的第一行包括数据,如文件名、行号和模块名称,都指示代码的位置。
  4. 粗体行:这些粗体行是这些调用的第二行,包括已处理代码的实际片段。

在在命令行和REPL中执行代码时,Traceback的输出之间存在一些差异。让我们考虑在REPL中执行相同示例并了解Traceback输出。

REPL:

>>> def welcome( name ):  
...     print( "Hello, " + nam )                                  
...     print( "Welcome to the Python program!")   
...   
>>> welcome( "James" )  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "<stdin>", line 2, in welcome  
NameError: name 'nam' is not defined  

正如我们在REPL代码段中所看到的,Traceback消息在文件名(file name)的位置返回了"",因为我们是通过标准输入键入的代码。此外,Traceback消息不显示已执行的代码行。

注意:如果你喜欢查看不同编程语言中的堆栈跟踪,那么在Python编程语言中,Traceback的外观与其他编程语言相比有明显的差异。大多数编程语言在顶部返回异常,然后从上到下依次处理最近的调用到最不常见的调用。

而在Python中,应该从下到上阅读Traceback。这非常有帮助,因为当Traceback返回时,终端通常位于输出底部,为我们提供了开始阅读Traceback的完美位置。

了解Python中一些常见的Traceback

一旦我们了解了如何在Python中读取Traceback,让我们来了解一些在编码时可能遇到的常见Traceback,以及它们的含义、引发它们的原因以及在它们的Traceback中可以找到的数据。

AttributeError

AttributeError异常在尝试访问对象上没有定义的属性时引发。Python的文档描述了何时引发AttributeError异常:

此异常在尝试引用或分配属性失败时引发。

让我们考虑下面的示例,演示了引发AttributeError异常的情况。

示例:

# 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'

解释:

在上面的代码片段中,我们定义了一个整数并尝试访问其属性。然而,当我们执行程序时,它引发了AttributeError异常,指出特定对象类型(在上面的示例中是int)没有访问的属性,即an_attribute。在错误的消息行中查看AttributeError异常可以帮助我们方便地识别我们试图访问的属性以及如何修复它。

通常,当引发此类异常时,这意味着我们可能正在处理不符合预期的实例。

让我们考虑另一个示例以更好地说明:

示例:

# 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_listlist类型,其中包含一个名为append()的方法。当我们收到AttributeError异常时,我们观察到它是在调用append()函数时引发的,这告诉我们我们可能不是在处理我们所期望的对象类型。

通常,当我们希望从方法或函数调用返回一个特定类型的对象,但最终得到的是None类型对象时,会发生这种情况。在上面的情况下,错误消息中会显示AttributeError: 'NoneType' object has no attribute 'append'

ImportError

ImportError异常在import语句出现问题时引发。如果要导入的模块或库无法找到,或者从库或模块导入某物并不在其中,那么我们将获得此异常,或其子类ModuleNotFoundError。Python的文档说明了何时引发ImportError异常:

此异常在import语句无法加载库或模块时引发。此外,当from ... import中的'from list'包含无法找到的名称时,也会引发此异常。

让我们考虑一个示例,演示了引发ImportErrorModuleNotFoundError的情况。

示例:

# 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 
    from collections import xyz
ImportError: cannot import name 'xyz' from 'collections' (D:\Python39\lib\collections\__init__.py)

解释:

在上面的代码片段中,我们尝试导入一个不存在的库或模块xyz,导致ModuleNotFoundError异常。另一方面,当我们尝试从已经存在的collections库导入不存在的模块xyz时,程序引发ImportError异常。错误的消息行底部显示了无法导入的特定内容,在这两种情况下都是xyz

IndexError

IndexError异常通常在我们尝试从序列或系列(例如元组或列表)中检索索引,而该索引在序列或系列中找不到时引发。Python的文档说明了何时引发IndexError异常:

此异常在序列或系列的下标超出范围时引发。

让我们考虑下面的示例,演示了引发IndexError异常的情况。

示例:

# 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的元素时,程序引发了IndexError异常。IndexError异常的错误消息不提供详细信息。我们可以看到错误消息中包含了一个序列引用,即超出范围,以及序列的类型,列表。连同Traceback的其余部分,这些信息通常足够帮助我们迅速识别如何修复问题。

KeyError

KeyError异常类似于IndexError异常,当我们尝试访问不在映射中的键时引发。通常出现在数据结构中,例如字典。Python的文档说明了何时引发KeyError异常:

此异常在字典(映射)键未在现有键集中找到时引发。

让我们考虑下面的示例,以了解KeyError异常是如何引发的。

示例:

# 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'

解释:

在上面的代码片段中,我们定义了一个名为mydict的字典,其中包含一些键和分配给每个键的值。然后,我们尝试访问字典中不存在的键的值。结果,程序引发KeyError异常,指出我们正在寻找的无法找到。

NameError

NameError异常在我们引用在代码行中未定义的变量、类、函数、模块或其他名称时引发。Python的文档说明了何时引发NameError异常:

此异常在未找到本地或全局名称时引发。

让我们考虑下面的示例,以了解NameError异常是如何引发的。

示例:

# 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

解释:

在上面的示例中,我们定义了一个名为myself()的函数,它以name作为参数。然而,当在打印某些语句时,我们在name的拼写中出错,写成了nam。然后,我们调用了该函数。结果,程序引发了NameError异常,因为名字'nam'在程序中未定义。

SyntaxError

SyntaxError异常通常在Python程序的语法不正确时引发。Python的文档说明了何时引发SyntaxError异常:

此异常在解析器遇到Python语法错误时引发。

让我们考虑一个示例,演示了引发SyntaxError异常的情况。

示例:

# 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

解释:

在上面的示例中,我们定义了一个名为myself()的函数,但忘记在函数定义之后包含冒号":"。结果,当我们执行该函数时,程序引发了SyntaxError异常,指出程序的语法有问题。位于代码行下方的^(尖号)表示问题的位置。

此外,我们可以看到SyntaxError的Traceback消息不显示常规的第一行,即"Traceback (most recent call last):"。这是因为SyntaxError异常是在Python尝试分析代码行时引发的,而代码行不是以文字方式处理的。

TypeError

TypeError异常在语法尝试使用无法执行该函数的实例时引发,例如尝试将整数与字符串相加,或在对象上调用len()函数,其中该对象的长度未指定。Python的文档说明了何时引发TypeError异常:

此异常在将函数或操作应用于错误类型的对象时引发。

让我们考虑下面的示例,以了解TypeError异常是如何引发的。

示例:

# 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'

解释:

在上面的示例中,我们定义了两个变量,一个是整数,一个是字符串。然后,我们执行了这些变量的加法操作,并尝试打印结果。然而,程序返回了TypeError异常,因为我们尝试将整数值与字符串值相加。

类似地,当我们对'int'数据类型的对象执行len()函数时,也会引发TypeError异常。

让我们考虑下面的示例,以了解相同的情况。

示例:

# 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()函数。然而,程序引发了TypeError异常,指出我们不能对'int'数据类型的对象执行len()函数。

ValueError

ValueError异常在对象的值不正确时引发。此异常类似于IndexError异常,因为在IndexError异常的情况下,索引值超出了序列的范围。而ValueError异常则适用于更一般的情况。Python的文档说明了何时引发ValueError异常:

此异常在函数或操作接收到具有正确类型但不合适值的参数时引发,状态未由更特定的异常(如IndexError)定义。

让我们考虑一个示例,演示了引发ValueError异常的情况。

示例:

# 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)

解释:

在上面的示例中,我们尝试解压四个值,但只得到了三个。结果,程序引发了ValueError异常。

让我们考虑另一个示例,演示了ValueError异常的情况。

示例:

# 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)

解释:

在上面的语法中,我们尝试解压太多的值。结果,程序返回ValueError异常,指出没有足够的值来解压(期望4个,得到3个)。

希望这些示例有助于你更好地理解Python中一些常见的Traceback。请随时提出任何其他问题或需要进一步的解释。

标签: Tkinter教程, Tkinter安装, Tkinter库, Tkinter入门, Tkinter学习, Tkinter入门教程, Tkinter, Tkinter进阶, Tkinter指南, Tkinter学习指南, Tkinter进阶教程, Tkinter编程