Python异常处理进阶
困难2让程序不“崩溃”的秘密武器:Python异常处理进阶
小朋友,你写程序时遇到过“崩溃”吗?比如用户输入“0”作为除数,程序就直接报错停止了。或者用户不小心输入了字母“abc”,结果程序“啪”地就挂了。其实,我们可以用 异常处理 来“接住”这些错误,就像接住掉下来的杯子一样,让程序继续稳稳地运行。
今天我们学习更高级的用法:else 和 finally。它们能让你的程序在遇到错误时更聪明、更体贴。
想象一下:你做化学实验,先小心倒液体(可能洒出来),如果洒了就用抹布擦(捕获异常)。如果没洒,就记录实验结果(else)。不管洒没洒,最后都要洗手(finally)。
Python 的 try-except-else-finally 就是这套流程。下面我们来一步步学会使用它。
1. 为什么需要异常处理?
程序运行的时候,可能会遇到各种“意外”:
- 用户输入了不该输入的内容(比如“abc”当成数字)
- 文件突然不见了
- 网络连接中断
如果不处理,程序会直接报错并停止运行,用户会一脸懵。用异常处理,我们可以优雅地告诉用户“哪里出错了”,并且给用户重新尝试的机会。
2. 基本结构:try 和 except
最基础的是 try-except:
# 让用户输入一个数字
try:
# 用户输入的内容可能不是整数
num = int(input("请输入一个整数:"))
except ValueError:
# 如果输入的不是整数,就捕获这个错误
print("你输入的不是整数哦,请重新运行!")
生活例子:就像你请朋友帮忙倒水,如果朋友没倒好洒了(异常),你就拿起抹布擦(处理)。
3. 多个 except:分别处理不同错误
一个 try 后面可以跟好几个 except,每个 except 处理一种错误类型。这样不同的问题,可以用不同的方式处理。
# 两个数字相除
try:
a = int(input("请输入被除数:")) # 被除数
b = int(input("请输入除数:")) # 除数
result = a / b # 除法运算
except ValueError:
print("输入的不是整数,请重新运行程序。")
except ZeroDivisionError:
print("除数不能为0,请重试。")
常见错误:新手容易忘记写错误类型,写成 except: 而没有指定类型,这样虽然能捕获所有错误,但无法针对不同错误给出不同提示。尽量明确写出错误类型。
4. else:没出错时才做的事
else 块里的代码 只有没有发生异常 时才会执行。它适合放“成功后的操作”——比如打印结果、保存数据、说“恭喜”等。
# 要求用户输入两个数字做除法
try:
a = int(input("请输入被除数:")) # 被除数
b = int(input("请输入除数:")) # 除数
result = a / b # 结果
except ValueError:
print("输入的不是整数,请重新运行程序。")
except ZeroDivisionError:
print("除数不能为0,请重试。")
else:
# 没有发生任何异常时执行
print("计算成功!结果是:", result)
生活例子:你考试前检查文具(try),如果发现笔没水了(except),就换一支。如果所有笔都正常(没异常),就安心考试(else)。
注意:else 必须在所有 except 之后,而且不能单独存在,必须和 try 一起用。
5. finally:无论如何都要做的事
finally 块厉害的地方在于:不管有没有异常,它都会执行。哪怕 try 里写了 return 或者程序要退出了,finally 也会跑完。
finally 适合做“清理工作”——比如关闭文件、断开网络连接、打印“再见”提示等。
# 带 finally 的除法例子
try:
a = int(input("请输入被除数:"))
b = int(input("请输入除数:"))
result = a / b
except ValueError:
print("输入的不是整数。")
except ZeroDivisionError:
print("除数不能为0。")
else:
print("计算成功!结果是:", result)
finally:
# 无论是否出错,都会执行
print("程序结束,感谢使用。")
生活例子:你去游泳(可能游得好,也可能呛水),但是不管怎样,游完之后你都要去冲澡(finally)。
常见错误:把 finally 和 else 搞混。记住:else 只在没异常时执行,finally 任何时候都执行。
6. 常见错误与避坑指南
-
错误类型写错:比如把
ZeroDivisionError写成ZeroDivisionErrorr(多了一个r),程序会报错说“这个错误没定义”。一定要用 Python 内置的错误名称。 -
except 后面不写错误类型:
except:会捕获所有异常,但这样你就不知道具体是什么错误,不利于调试。最好明确写出。 -
else 的位置不对:
else必须在所有except之后,不能放在except前面。 -
finally 里写 return:如果你在
finally里写了return,它会覆盖try或except里的return,导致意外结果。一般不要在finally里写 return。
7. 完整示例:让用户直到输入正确为止
把前面学的结合起来,做一个“防崩溃”的除法计算器。用户输入错误可以重试,直到成功为止。
# 提示用户直到输入正确,完成除法
while True: # 无限循环,直到正确才退出
try:
# 用户输入两个数字
a = int(input("请输入被除数:")) # 被除数,整数
b = int(input("请输入除数:")) # 除数,整数
result = a / b # 计算结果
except ValueError:
print("你输入的不是整数,请重新输入!")
except ZeroDivisionError:
print("除数不能为0,请重新输入!")
else:
# 没有异常时执行,打印结果并退出循环
print(f"计算成功!{a} ÷ {b} = {result}")
break # 跳出 while 循环
finally:
# 每次循环结束都打印分隔线(无论成功还是失败)
print("--- 本次尝试结束 ---")
print("程序正常退出,谢谢使用!")
运行这个程序,即使输错多次,也不会崩溃,会一直提示直到正确为止。
8. 相关指引:还能学哪些?
- 抛出异常:用
raise手动制造异常,比如当用户输入负数时,主动抛出ValueError。 - 自定义异常:你可以创建自己的异常类,比如
AgeError(年龄错误),让错误信息更具体。 - 异常处理的最佳实践:不要用异常处理代替普通的条件判断(比如检查除数是否为0可以用
if b == 0提前判断),异常处理只用于“真正意外”的情况。
掌握了异常处理,你的程序就能从“玻璃人”变成“铁人”——遇到问题不会轻易倒下,而是给你机会改正。快去试试吧!
例题精讲
在Python中,以下关于try-except-else-finally语句的执行顺序描述中,哪一项是正确的?
在Python中,自定义异常类必须直接或间接继承自BaseException类。
阅读以下代码,当输入为'0'时,输出是什么?请填写。
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print('除数不能为0')
raise
else:
print('计算成功')
finally:
print('执行完毕')
try:
divide(10, 0)
except ZeroDivisionError:
print('捕获到异常')
输出顺序:
除数不能为0
___
捕获到异常在Python中,使用raise ... from ...语句的主要目的是什么?
在Python的try-finally语句中,如果finally块中包含了return语句,则会覆盖try块中的return语句。