当前位置:首页>python>Python异常处理完全指南(上)

Python异常处理完全指南(上)

  • 2026-09-03 21:49:35
Python异常处理完全指南(上)

程序跑着跑着突然中断,终端甩出一长串红色报错——这就是异常。本篇从「求两个整数的商」出发,讲清异常是什么、怎么读堆栈,以及 try-except 怎么用。

本篇目录

1. 从一个小需求说起

2. 什么是异常

3. 如何阅读异常信息

4. 用 if-else 堵漏洞及其局限

5. 异常类的继承体系

6. try-except 基础语法

7. 捕获指定异常

1. 从一个小需求说起

需求:键盘录入两个整数,求商。

num1 = int(input("请录入第一个数:"))num2 = int(input("请录入第二个数:"))print(f"商:{num1 // num2}")

正常输入 10 和 2 时:

请录入第一个数:10请录入第二个数:2商:5

输入稍有偏差就会崩溃:

输入情况
典型异常
录入非数字,如 abc
ValueError
除数为 0
ZeroDivisionError
录入带符号或空串等边界值
ValueError
 等

业务逻辑很简单,真正让程序挂掉的是运行时错误事件——异常。

2. 什么是异常

**异常(Exception)**是程序运行时发生的错误事件,会打断正常执行流程。一旦产生且未被处理,解释器通常会打印堆栈信息,然后终止当前程序。

可以把它理解成:

1. 某行代码触发了错误条件

2. 解释器创建对应的异常对象

3. 沿着调用栈向上寻找能处理它的 except

4. 找不到就让程序异常退出

常见触发源:非法输入、除零、下标越界、文件不存在、网络超时、类型不匹配等。

3. 如何阅读异常信息

以除零为例:

print(10 // 0)

终端大致会输出:

Traceback (most recent call last): File "demo.py", line 1, in <module>  print(10 // 0)ZeroDivisionError: integer division or modulo by zero

阅读顺序建议自下而上:

部分
含义
最后一行异常类型
如 ZeroDivisionError,先看「出了什么错」
冒号后的描述
错误说明,如 division by zero
上面的堆栈帧
从哪里调用到这里,哪一行触发
File "...", line N
精确定位文件与行号

养成习惯:先看异常类型和最后一行描述,再顺着堆栈找自己的代码行。

4. 用 if-else 堵漏洞及其局限

可以在转换和除法前手动校验:

user_input1 = input("请录入第一个数:")if user_input1.isdigit():  num1 = int(user_input1)  user_input2 = input("请录入第二个数:")  if user_input2.isdigit():    num2 = int(user_input2)    if num2 != 0:      print(f"商:{num1 // num2}")    else:      print("错误:除数不能为零!")  else:    print("错误:第二个数不是有效的整数!")else:  print("错误:第一个数不是有效的整数!")

这种写法能挡住一部分非法输入,但有明显缺点:

1. 代码臃肿:业务与防护逻辑缠在一起

2. 可读性差:层层嵌套,主流程被淹没

3. 维护成本高:每加一种校验就多一层分支

4. 很难堵全:例如 isdigit() 不接受负数 -3

结论:简单前置校验可以有,但系统性错误处理应交给异常机制。

5. 异常类的继承体系

Python 内置异常是一棵继承树。开发中最常接触的是 Exception 及其子类;KeyboardInterrupt、SystemExit 等直接挂在 BaseException 下,一般不要用裸 except: 去吞掉它们。

精简示意:

BaseException ├── KeyboardInterrupt ├── SystemExit ├── GeneratorExit └── Exception                    # 业务代码通常捕获这一支   ├── ArithmeticError   │    └── ZeroDivisionError   ├── LookupError   │    ├── IndexError   │    └── KeyError   ├── OSError   │    ├── FileNotFoundError   │    └── PermissionError   ├── TypeError   ├── ValueError   └── ...

匹配规则:except 会捕获该类及其所有子类。因此要把更具体的异常写在前面,把更宽泛的(如 Exception)放在后面。

6. try-except 基础语法

try:  可能出错的代码except:  出错后的处理代码

把求商改成异常处理版:

try:  num1 = int(input("请录入第一个数:"))  num2 = int(input("请录入第二个数:"))  print(f"商:{num1 // num2}")except:  print("程序出现异常")print("后续逻辑代码1")print("后续逻辑代码2")

执行路径:

有异常:产生异常 → 找最近 except → 处理 → 继续往下跑无异常:跳过 except → 继续往下跑

注意:裸 except: 会捕获几乎所有异常,生产代码应尽量写成具体类型,至少写成 except Exception:。

7. 捕获指定异常

多个 except自上而下匹配,命中后不再继续往下找:

try:  num1 = int(input("请录入第一个数:"))  num2 = int(input("请录入第二个数:"))  print(f"商:{num1 // num2}")except ValueError:  print("输入有误,请输入整数!")except ZeroDivisionError:  print("除数不能为 0!")except Exception:  print("意外异常")print("后续逻辑代码1")
异常
常见触发场景
提示文案示例
ValueErrorint("abc")
请输入整数
ZeroDivisionErrorn // 0
除数不能为 0
Exception
其他未预期错误
兜底日志/提示

也可以用元组一次捕获多种类型:

except (ValueError, TypeError) as e:  print(f"输入类型或格式错误:{e}")

下篇继续讲:获取异常信息、traceback、else/finally、raise、自定义异常与异常传递。

最新文章

随机文章