Python入门教程第52篇 异常处理之try…except

Posted 不剪发的Tony老师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python入门教程第52篇 异常处理之try…except相关的知识,希望对你有一定的参考价值。

本篇我们将会学习如何使用 try…except 语句处理程序中的异常。

Python 中存在两种类型的错误:语法错误(syntax error)和异常(exception)。

语法错误

当我们编写了无效的 Python 代码时,程序将会返回语法错误。例如:

current = 1
if current < 10
current += 1

运行以上代码将会返回下面的错误:

File "d:/python/try-except.py", line 2
    if current < 10
                  ^
SyntaxError: invalid syntax

以上示例中,Python 解释器检测到了错误,因为 if 语句后面缺少一个冒号(:)。Python 解释器显示了错误所在的文件名和行号,我们可以基于这些信息找到并修改错误。

异常

即使代码中没有语法错误,它在执行过程中也可以产生错误。Python 将执行过程中的错误称为异常。异常产生的主要原因来自代码执行的环境。例如:

  • 读取了一个不存在的文件。
  • 连接了一个停止运行的远程服务器。
  • 错误的用户输入。

当异常发生时,程序不会自动对其进行处理,而是产生一个错误信息。例如,以下程序用于计算销售增长率:

# 获取净销售额
print('输入净销售额')

previous = float(input('- 上一期:'))
current = float(input('- 本期:'))

# 计算销售额变化的百分比
change = (current - previous) * 100 / previous

# 显示结果
if change > 0:
    result = f'Sales increase abs(change)%'
else:
    result = f'Sales decrease abs(change)%'

print(result)

以上代码执过程如下:

  • 首先,提升用户输入两个数字:上一期和本期的净销售额。
  • 然后,计算销售增长率并打印结果。

当我们运行代码并输入“120’”作为本期净销售额时,Python 解释器将会返回以下输出:

输入净销售额
- 上一期:100
- 本期:120'
Traceback (most recent call last):
  File "d:/python/try-except.py", line 5, in <module>
    current = float(input('- Current period:'))
ValueError: could not convert string to float: "120'"

Python 解释器显示了包含异常详细信息的错误跟踪(traceback):

  • 引起异常的源文件的路径(d:/python/try-except.py)。
  • 引起异常的代码行(line 5)。
  • 引起异常的语句(current = float(input(’- Current period:’)))。
  • 异常的类型(ValueError)。
  • 错误信息:ValueError: could not convert string to float: “120’”。

由于 float() 函数无法将字符串“120’”转换为数字,Python 解释器产生了一个 ValueError 异常。

Python 提供了不同类型的异常,例如 TypeError、NameError 等。

异常处理

为了使得程序更加健壮,我们需要处理可能的异常。也就是说,我们需要捕获异常并通知用户,以便他们能够修复异常。

处理异常的推荐方式不是直接显示 Python 解释器返回的错误,而是显示一个更加友好的信息。为此,我们可以使用 try…except 语句:

try:
    # 业务代码
except:
    # 错误处理

以上语句的执行过程如下:

  • 首先,执行 try 分支中的语句。
  • 如果没有发生异常,执行完 try 分支语句后跳过 except 分支。
  • 如果 try 分支中的任何语句执行出错,停止执行后面的语句并且执行 except 分支中的语句。

以下流程图演示了 try…except 语句的执行过程:

因此,使用 try…except 语句处理异常时,我们需要将可能导致异常的代码放在 try 分支中,将处理异常的代码放在 except 分支中。

下面我们重新上文中的示例,使用 try…except 语句处理异常:

try:
    # 获取净销售额
    print('输入净销售额')

    previous = float(input('- 上一期:'))
    current = float(input('- 本期:'))

    # 计算销售额变化的百分比
    change = (current - previous) * 100 / previous

    # 显示结果
    if change > 0:
        result = f'销售额增加了 abs(change)%'
    else:
        result = f'销售额减少了 abs(change)%'

    print(result)
except:
    print('错误!净销售额必须是一个数字。')

If you run the program again and enter the net sales which is not a number, the program will issue the message that you specified in the except block instead:

输入净销售额
- 上一期:100
- 本期:120'
错误!净销售额必须是一个数字。

捕获特定异常

当我们为上一期净销售额输入数字 0 时,将会返回以下信息:

输入净销售额
- 上一期:0
- 本期:100
错误!净销售额必须是一个数字。

在这种情况下,上一期和本期的净销售额都是数字,但是程序仍然返回了一个错误信息。这是因为发生了另一个异常。

try…except 语句可以处理特定的异常。为了捕获指定的异常,我们可以在 except 关键字后面加上异常的类型:

try:
    # 业务代码
except ValueError as error:
    # 异常处理

例如:

try:
    # 获取净销售额
    print('输入净销售额')

    previous = float(input('- 上一期:'))
    current = float(input('- 本期:'))

    # 计算销售额变化的百分比
    change = (current - previous) * 100 / previous

    # 显示结果
    if change > 0:
        result = f'销售额增加了 abs(change)%'
    else:
        result = f'销售额减少了 abs(change)%'

    print(result)
except ValueError:
    print('错误!净销售额必须是一个数字。')

此时如果我们输入一个字符串作为净销售额,将会返回相同的错误信息。但是,如果我们输入数字 0 作为上一期的净销售额:

输入净销售额
- 上一期:0
- 本期:100

程序将会返回以下错误:

Traceback (most recent call last):
  File "d:/python/try-except.py", line 9, in <module>
    change = (current - previous) * 100 / previous
ZeroDivisionError: float division by zero

此时返回的异常类型为 ZeroDivisionError。以下语句导致了除零错误:

change = (current - previous) * 100 / previous

原因就是变量 previous 的值为零。

处理多个异常

try…except 语句可以指定多个 except 分支,用于处理多个异常:

try:
    # 业务代码
except Exception1 as e1:
    # 异常处理
except Exception2 as e2:
    # 异常处理
except Exception3 as e3:
    # 异常处理

这种方式可以针对不同类型的异常分别进行处理。

如果想要对几种类型的异常进行相同的处理,可以将它们放在一个 except 分支中:

try:
    # 业务代码
except (Exception1, Exception2):
    # 异常处理

以下示例使用 try…except 语句对 ValueError 和 ZeroDivisionError 异常分别进行了处理:

try:
    # 获取净销售额
    print('输入净销售额')

    previous = float(input('- 上一期:'))
    current = float(input('- 本期:'))

    # 计算销售额变化的百分比
    change = (current - previous) * 100 / previous

    # 显示结果
    if change > 0:
        result = f'销售额增加了 abs(change)%'
    else:
        result = f'销售额减少了 abs(change)%'

    print(result)
except ValueError:
    print('错误!净销售额必须是一个数字。')
except ZeroDivisionError:
    print('错误!上一期净销售额不能为零。')

当我们输入数字 0 作为上一期的净销售额时:

输入净销售额
- 上一期:0
- 本期:100

将会返回以下错误:

错误!上一期净销售额不能为零。

推荐在异常列表的最后增加一个捕获 Exception 的代码块,用于处理其他通用错误:

try:
    # 获取净销售额
    print('输入净销售额')

    previous = float(input('- 上一期:'))
    current = float(input('- 本期:'))

    # 计算销售额变化的百分比
    change = (current - previous) * 100 / previous

    # 显示结果
    if change > 0:
        result = f'销售额增加了 abs(change)%'
    else:
        result = f'销售额减少了 abs(change)%'

    print(result)
except ValueError:
    print('错误!净销售额必须是一个数字。')
except ZeroDivisionError:
    print('错误!上一期净销售额不能为零。')
except Exception as error:
    print(error)

总结

  • Python 使用 try…except 语句处理异常。
  • 尽可能地在 except 模块中指定具体的异常。
  • 使用 except Exception 语句捕获其他异常。

以上是关于Python入门教程第52篇 异常处理之try…except的主要内容,如果未能解决你的问题,请参考以下文章

Python入门教程第54篇 异常处理之try…except…else

python学习第七周之异常处理

芝麻HTTP:Python爬虫入门之URLError异常处理

Python语言之异常处理与测试

python9之异常处理

Python学习第15篇:面向对象之异常处理