异常处理
本节目标
学完这一节,你会知道:
- 什么是异常,为什么程序会因为错误而停止
- 如何用
try/except捕获错误 - 如何分别处理不同类型的错误
else和finally分别什么时候执行- 如何写一个不会轻易崩掉的小计算器
异常处理不是为了隐藏错误,而是为了让程序遇到可预期的问题时,能给用户一个清楚的提示。
先跑一个例子
新建文件 safe_divide.py,写入:
try:
number = int(input("请输入一个整数:"))
result = 100 / number
print(f"100 / {number} = {result}")
except ValueError:
print("输入错误:请输入整数")
except ZeroDivisionError:
print("数学错误:不能除以 0")
运行:
python3 safe_divide.py
分别试试输入:
20abc0
你会发现,程序不会直接崩溃,而是输出不同提示。
为什么需要异常处理?
没有异常处理时,用户输入不符合预期,程序就会报错停止:
number = int(input("请输入一个整数:"))
print(100 / number)
如果用户输入 abc,int("abc") 会失败。
如果用户输入 0,100 / 0 会失败。
这些运行时出现的问题,就叫异常。
try / except 基础
基本结构:
try:
可能出错的代码
except 错误类型:
出错后执行的代码
例子:
try:
age = int("abc")
except ValueError:
print("转换失败")
try 里的代码如果没有出错,except 不会执行。
try 里的代码如果出错,并且错误类型匹配,程序会进入对应的 except。
常见异常类型
| 异常 | 常见原因 |
|---|---|
ValueError |
值不合适,比如 int("abc") |
TypeError |
类型不合适,比如 "a" + 1 |
ZeroDivisionError |
除以 0 |
IndexError |
列表索引超出范围 |
KeyError |
字典里没有这个键 |
FileNotFoundError |
文件不存在 |
AttributeError |
对象没有这个属性或方法 |
刚开始不用背,遇到报错时先看最后一行的异常名字。
捕获多种异常
不同错误可以给不同提示:
try:
number = int(input("请输入数字:"))
result = 10 / number
print(result)
except ValueError:
print("请输入有效数字")
except ZeroDivisionError:
print("不能除以 0")
也可以获取错误信息:
try:
int("abc")
except ValueError as error:
print(f"错误信息:{error}")
as error 会把异常对象保存到变量 error。
else 和 finally
else:只有 try 没出错时才执行。
finally:不管有没有出错,最后都会执行。
try:
number = int(input("请输入整数:"))
except ValueError:
print("输入不是整数")
else:
print(f"转换成功:{number}")
finally:
print("程序结束")
适合用 finally 做收尾工作,比如关闭文件、断开连接。
raise:主动抛出异常
有时你想主动告诉程序:“这个值不合法”。
def check_age(age):
if age < 0:
raise ValueError("年龄不能为负数")
if age > 150:
raise ValueError("年龄不合理")
return "年龄正常"
try:
print(check_age(-1))
except ValueError as error:
print(error)
刚入门时,先学会读懂 raise。以后写项目时,它会经常用来校验数据。
逐行拆解
再看开头的例子:
try:
number = int(input("请输入一个整数:"))
这一行可能因为用户输入非数字而出错。
result = 100 / number
这一行可能因为 number 是 0 而出错。
except ValueError:
print("输入错误:请输入整数")
如果转换整数失败,执行这里。
except ZeroDivisionError:
print("数学错误:不能除以 0")
如果除以 0,执行这里。
自己改一改
把 safe_divide.py 改成循环版本:
while True:
text = input("请输入一个整数,输入 q 退出:")
if text == "q":
print("再见")
break
try:
number = int(text)
result = 100 / number
print(f"结果:{result}")
except ValueError:
print("请输入整数")
except ZeroDivisionError:
print("不能除以 0")
然后继续改:
- 支持输入大写
Q退出 - 结果保留两位小数
- 每次计算结束后输出一条分隔线
实战:安全的计算器
新建文件 safe_calculator.py:
try:
a = float(input("第一个数字:"))
op = input("运算符(+ - * /):")
b = float(input("第二个数字:"))
if op == "+":
result = a + b
elif op == "-":
result = a - b
elif op == "*":
result = a * b
elif op == "/":
if b == 0:
raise ZeroDivisionError("除数不能为 0")
result = a / b
else:
raise ValueError("不支持的运算符")
print(f"结果:{result}")
except ValueError as error:
print(f"输入错误:{error}")
except ZeroDivisionError as error:
print(f"数学错误:{error}")
这个例子把输入转换、运算符判断、除零检查放在了一起。
常见错误
1. 把太多代码放进 try
不推荐:
try:
name = input("名字:")
age = int(input("年龄:"))
print("很多不相关的代码")
except ValueError:
print("年龄错误")
尽量只把可能出错的关键代码放进 try,这样更容易定位问题。
2. 裸 except
不推荐:
try:
number = int(input("数字:"))
except:
print("出错了")
推荐捕获具体异常:
except ValueError:
print("请输入数字")
3. except 顺序太宽泛
如果写了 except Exception,它应该放在最后。
try:
number = int("abc")
except ValueError:
print("值错误")
except Exception:
print("其他错误")
4. 以为异常处理能修复所有问题
异常处理只能处理已经预想到的错误。代码逻辑本身错了,还是要回去修改逻辑。
小练习
练习 1:安全年龄输入
让用户输入年龄:
- 如果不是整数,提示“请输入整数”
- 如果小于 0,提示“年龄不能为负数”
- 否则输出年龄
练习 2:安全取列表元素
给定:
names = ["小明", "小红", "小刚"]
让用户输入索引,输出对应名字。如果索引越界,提示“没有这个编号”。
练习 3:安全除法
让用户输入两个数字,输出第一个数字除以第二个数字的结果。处理非数字和除以 0 两种情况。
参考答案
练习 1:
try:
age = int(input("请输入年龄:"))
if age < 0:
print("年龄不能为负数")
else:
print(f"年龄:{age}")
except ValueError:
print("请输入整数")
练习 2:
names = ["小明", "小红", "小刚"]
try:
index = int(input("请输入编号:"))
print(names[index])
except ValueError:
print("请输入整数编号")
except IndexError:
print("没有这个编号")
练习 3:
try:
a = float(input("第一个数字:"))
b = float(input("第二个数字:"))
print(a / b)
except ValueError:
print("请输入数字")
except ZeroDivisionError:
print("不能除以 0")
小结
这一节你学会了:
- 异常是程序运行时出现的问题
try/except可以捕获并处理异常- 不同异常可以写不同
except else在没有异常时执行,finally总会执行raise可以主动抛出异常
下一章我们会学习函数。函数可以把一段代码封装起来,让程序更清楚、更容易复用。
报错不是敌人,它只是说话有点直
异常处理会让程序遇到意外时不至于原地趴下。你可以故意输入 abc、0、奇怪的内容,看看 try/except 怎么接住它们。马哥提醒你:会读报错的人,学编程会少很多内耗。
还没有评论,来抢沙发吧!