Python 中的错误与异常

PythonBeginner
立即练习

介绍

在这个 Lab 中,你将获得对 Python 中错误(errors)和异常(exceptions)的实践理解。我们将探讨如何识别阻止代码执行的常见语法错误(syntax errors),识别运行时发生的各种类型的异常,并清晰地区分 Python 编程中这两个基本概念。

通过动手练习,你将学会发现和修复诸如缩进不正确、缺少语法元素以及其他常见陷阱等问题,从而为编写健壮且无错误的 Python 代码打下坚实的基础。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 100%。获得了学习者 100% 的好评率。

识别语法错误

在这一步,我们将探讨 Python 中常见的语法错误(syntax errors)。当代码违反了语言的语法规则时,就会发生语法错误,这会阻止解释器理解和执行代码。这些错误在程序开始运行之前就会被检测到。

必要的文件 syntax_errors.py 已为你创建在 ~/project 目录下。

首先,我们介绍一个 IndentationError(缩进错误)。从 WebIDE 左侧的文件浏览器中打开 syntax_errors.py。添加以下包含不正确缩进的代码:

for i in range(5):
    print(i)
  print("This line has incorrect indentation")

保存文件。现在,打开集成终端并运行脚本:

python syntax_errors.py

你将看到一个 IndentationError。Python 解释器期望代码块(如 for 循环中的代码块)具有一致的缩进级别。

  File "/home/labex/project/syntax_errors.py", line 3
    print("This line has incorrect indentation")
                                                ^
IndentationError: unindent does not match any outer indentation level

现在,我们修复缩进,但引入另一个不同的 SyntaxError(语法错误)。将 syntax_errors.py 中的代码修改为以下内容。注意第一行末尾缺少冒号(:)。

for i in range(5)
    print(i)
    print("This line has correct indentation")

保存文件并再次从终端运行它:

python syntax_errors.py

这次,你将得到一个 SyntaxError。Python 中的 for 循环语句要求末尾有一个冒号,以表示代码块的开始。

  File "/home/labex/project/syntax_errors.py", line 1
    for i in range(5)
                     ^
SyntaxError: expected ':'

最后,我们更正冒号,但引入另一个常见的 SyntaxError:未终止的字符串。将 syntax_errors.py 文件修改如下。字符串 "hello' 以双引号开头,但以单引号结尾。

for i in range(5):
    print("hello')

保存文件并运行它:

python syntax_errors.py

你将遇到一个 SyntaxError,因为字符串没有用匹配的引号正确闭合。

  File "/home/labex/project/syntax_errors.py", line 2
    print("hello')
          ^
SyntaxError: unterminated string literal (detected at line 2)

这些示例说明,在程序能够运行之前,必须修复语法错误。始终密切关注缩进、冒号等必需的符号以及匹配的引号。

识别常见异常

在这一步,我们将探讨常见的异常(exceptions)。与语法错误不同,异常发生在程序执行期间。代码在语法上是正确的,但在运行时发生了错误。

文件 common_exceptions.py 已在 ~/project 目录下为你准备好。

首先,我们来引发一个 ZeroDivisionError(除以零错误)。在编辑器中打开 common_exceptions.py 并添加以下代码:

numerator = 10
denominator = 0
result = numerator / denominator
print(result)

保存文件并从终端运行它:

python common_exceptions.py

程序开始运行,但会停止并显示一个 ZeroDivisionError。在数学上,除以零是未定义的,Python 会引发此异常来指示该问题。

Traceback (most recent call last):
  File "/home/labex/project/common_exceptions.py", line 3, in <module>
    result = numerator / denominator
ZeroDivisionError: division by zero

接下来,我们触发一个 NameError(名称错误)。当你尝试使用尚未定义的变量时,会发生这种情况。将 common_exceptions.py 的内容替换为以下代码:

print(undefined_variable)

保存文件并运行它:

python common_exceptions.py

你将得到一个 NameError,因为解释器不知道 undefined_variable 指代什么。

Traceback (most recent call last):
  File "/home/labex/project/common_exceptions.py", line 1, in <module>
    print(undefined_variable)
NameError: name 'undefined_variable' is not defined

现在,我们来看一个 TypeError(类型错误)。当你尝试对不合适类型的对象执行操作时,会发生这种情况。将 common_exceptions.py 的内容替换为以下代码:

print("Hello" + 5)

保存并运行脚本:

python common_exceptions.py

你将看到一个 TypeError。Python 不允许你直接将字符串(string)和整数(integer)相加(+)。

Traceback (most recent call last):
  File "/home/labex/project/common_exceptions.py", line 1, in <module>
    print("Hello" + 5)
TypeError: can only concatenate str (not "int") to str

最后,我们演示一个 IndexError(索引错误)。当你尝试使用超出范围的索引来访问序列(如列表 list)的元素时,会发生这种情况。将 common_exceptions.py 的内容替换为以下代码:

my_list = [1, 2, 3]
print(my_list[5])

保存并运行脚本:

python common_exceptions.py

你将得到一个 IndexError。列表 my_list 包含三个元素,因此其有效索引是 0、1 和 2。访问索引 5 是不可能的。

Traceback (most recent call last):
  File "/home/labex/project/common_exceptions.py", line 2, in <module>
    print(my_list[5])
IndexError: list index out of range

理解这些常见异常是学习调试 Python 代码的关键部分。

区分错误 (Errors) 与异常 (Exceptions)

在最后一步中,我们将明确区分语法错误(syntax errors)和异常(exceptions)。这个区别对于 Python 编程和调试至关重要。

语法错误(或解析错误 Parsing Errors):

  • 这些是你代码结构中违反 Python 规则的错误。
  • Python 解释器在你的程序开始运行之前就会发现这些错误。
  • 存在语法错误的程序根本无法执行。
  • 示例:IndentationError(缩进错误)、缺少冒号、括号或引号不匹配。

异常(或运行时错误 Runtime Errors):

  • 这些错误发生在语法正确的程序执行期间
  • 当程序遇到意外情况时(例如除以零或访问不存在的文件),就会发生这些错误。
  • 如果不进行处理(handle),异常会导致你的程序崩溃并打印出回溯信息(traceback)。
  • 示例:ZeroDivisionErrorNameErrorTypeErrorIndexError

让我们实际看看这一点。从文件浏览器中打开文件 error_vs_exception.py。添加以下代码,其中包含一个语法错误(缺少冒号)和一行将导致运行时异常的代码。

## This line has a syntax error (missing colon)
for i in range(5)
    print(i)

## This line will cause an exception (division by zero)
result = 10 / 0
print(result)

保存文件并尝试运行它:

python error_vs_exception.py

请注意,你立即得到了一个 SyntaxError。解释器在运行任何代码之前会检查整个文件的语法是否正确。它会发现缺少冒号并停止,甚至没有到达包含 10 / 0 的那一行。

  File "/home/labex/project/error_vs_exception.py", line 2
    for i in range(5)
                     ^
SyntaxError: expected ':'

现在,我们来修复语法错误。在 error_vs_exception.py 中,为 for 循环行添加缺失的冒号:

## The syntax error is now fixed
for i in range(5):
    print(i)

## This line will cause an exception (division by zero)
result = 10 / 0
print(result)

保存文件并再次运行它:

python error_vs_exception.py

这次,程序在语法上是正确的,所以它开始执行。for 循环执行并打印数字 0 到 4。然后,当程序尝试执行 result = 10 / 0 时,它遇到了运行时问题并引发了 ZeroDivisionError,导致程序崩溃。

0
1
2
3
4
Traceback (most recent call last):
  File "/home/labex/project/error_vs_exception.py", line 6, in <module>
    result = 10 / 0
ZeroDivisionError: division by zero

这清楚地表明,语法错误会阻止执行,而异常发生在执行期间。在后续的实验(Lab)中,你将学习如何优雅地处理异常,以防止它们导致程序崩溃。

总结

在这个实验(Lab)中,你学习了 Python 中错误(errors)和异常(exceptions)之间的根本区别。你首先识别并修复了常见的语法错误,例如 IndentationError(缩进错误)和因缺少冒号导致的 SyntaxError(语法错误),理解了这些错误会完全阻止程序运行。

接下来,你探索了几种常见的运行时异常,包括 ZeroDivisionErrorNameErrorTypeErrorIndexError。你看到了这些异常是如何在语法正确的代码中,在执行期间操作失败时发生的。最后,你通过观察 Python 解释器如何处理一个同时包含语法错误和潜在异常的文件,巩固了你的理解,证明了在执行开始之前会检查语法。这些知识为你编写和调试 Python 应用程序提供了至关重要的基础。