当前位置:首页>python>Python代码能跑就完了?90%的新手都栽在了这一步:异常处理

Python代码能跑就完了?90%的新手都栽在了这一步:异常处理

  • 2026-10-11 05:41:04
Python代码能跑就完了?90%的新手都栽在了这一步:异常处理

昨晚有个读者私信我:"我写的代码在自己电脑上跑得好好的,发给同事用就报错,怎么办?"

我让他把报错截图发过来一看——典型的"用户输入不合法"导致程序崩溃。他写的代码,大概长这样:

age = input("请输入你的年龄:")age = int(age)print(f"你今年{age}岁")

他自己测试,永远输入"25",代码没问题。但同事不小心输入了"二十五",程序直接抛出ValueError崩掉了。

这就是今天要聊的话题——异常处理。从"能跑"到"稳跑",是每个编程新手必须跨过的坎。

一、为什么你的代码总是"看着没问题,一用就崩"

我总结了一下,新手写代码最容易崩的几个场景,基本就这几类:

1. 用户输入不规范:上面那个int()转换就是典型。用户可能输入字母、空格、甚至直接回车。

2. 文件不存在:你写open("data.txt")读文件,但用户没把这个文件放在指定位置。

3. 网络请求失败:爬虫或者调API时,网络抖一下、接口返回500,程序就抛异常。

4. 除数为0:计算平均分、分页时除以用户输入的数字,结果是个0。

5. 列表下标越界:你从列表里取第5个元素,但用户只给了3个。

这些场景有个共同点——不是你的代码逻辑错了,而是外部输入或环境变了。一个真正"稳"的程序,必须能优雅地处理这些意外。

二、try-except:让你的程序"会自救"

Python 提供了一个非常简单的机制——try-except,说白了就是"试试这段代码会怎么样,出了问题就按我的方案处理"。

最基础的用法:

try:    age = int(input("请输入你的年龄:"))    print(f"你今年{age}岁")except ValueError:    print("输入有误,请输入数字")

这样,用户输入"二十五"的时候,程序会打印"输入有误,请输入数字",而不是直接崩掉。这就是异常处理的核心思想——把可能出错的代码包起来,给它一个兜底方案。

更完整的写法是 try-except-else-finally 四个一起用:

try:    f = open("data.txt", "r", encoding="utf-8")    content = f.read()except FileNotFoundError:    print("文件不存在")else:    print("读取成功,共", len(content), "个字符")finally:    f.close()  # 不管出没出错,文件都要关掉

四个块的作用:

- try:放可能出错的代码

- except:出错时执行,可以指定具体异常类型

- else:没出错时执行

- finally:不管出不出错都要执行(关文件、关数据库连接的场景必备)

三、5个新手最容易踩的坑,看完少走3个月弯路

坑1:except后面什么都不写

很多新手写except: pass,这样会让所有错误都被悄悄吞掉,bug难以发现。

# 错误写法 ❌try:    do_something()except:    pass# 正确写法 ✅try:    do_something()except ValueError as e:    print(f"参数错了:{e}")

坑2:把所有异常都用Exception一把抓

Exception 能抓住几乎所有异常,但这样会把你不想处理的错误(比如KeyboardInterrupt用户按Ctrl+C)也抓住,导致程序退不出。

建议只抓你预期的、想处理的异常类型。比如读文件就只抓FileNotFoundError,用户输入就只抓ValueError。

坑3:在finally里写return,吞掉异常

这个坑很隐蔽。如果try块里出了异常,但在finally里return了,异常会被吞掉,调用方完全不知道出过问题。finally一般只做"清理"工作(关文件、关连接),不要在里面return或抛新异常。

坑4:自己造异常,命名不规范

需要自定义异常时,类名要以Error结尾,比如UserNotFoundError,并且继承自Exception:

class UserNotFoundError(Exception):    """用户不存在"""    passraise UserNotFoundError("用户ID 1001 不存在")

坑5:用异常处理代替逻辑判断

能用if判断的就别用异常。比如判断一个文件存不存在,应该用os.path.exists(),而不是先try open然后except。异常是用来处理"意外"的,不是用来当普通流程控制的。

四、3个实战场景,看完就能用上

场景1:批量处理用户数据

假设你要处理一个用户列表,每个用户可能因为各种原因处理失败。一个失败不应该让整个程序停下来:

users = [{"name": "张三", "age": "25"}, {"name": "李四", "age": "abc"}]for user in users:    try:        age = int(user["age"])        print(f"{user['name']}今年{age}岁")    except (ValueError, KeyError) as e:        print(f"{user.get('name', '未知')}数据有问题:{e}")

这样张三会被正常处理,李四有问题会被跳过并打印提示,程序继续跑下去。

场景2:网络请求重试

爬虫或者调接口时,网络偶尔抽风很正常。我们可以用一个简单的重试机制:

import timedef fetch_data(url, max_retries=3):    for i in range(max_retries):        try:            response = requests.get(url, timeout=5)            return response.json()        except requests.RequestException as e:            print(f"第{i+1}次失败:{e}")            time.sleep(2)    raise Exception("重试3次后仍然失败")

场景3:资源清理,告别"文件句柄泄露"

前面finally的例子很经典,但Python有更优雅的写法——with语句。它能保证不管出不出错,文件都会被关掉:

try:    with open("data.txt", "r", encoding="utf-8") as f:        content = f.read()        process(content)except FileNotFoundError:    print("文件不存在")

推荐把所有"打开文件、连接数据库、申请锁"这类需要清理的操作,都用with包起来。这是Pythonic的写法,也是最不容易出错的写法。

说到底,代码能跑只是开始,能稳才算入门。一个真正合格的程序,不是在"理想情况下"能跑,而是在"用户乱搞、网络抽风、文件丢失"的情况下还能给出友好提示、不直接崩掉。

今天讲的是异常处理的"道",具体怎么用 try/except、怎么用 with、怎么自定义异常,都是"术"。道是"哪里该用、哪里不该用",术是"具体怎么写"。先有道,再练术,顺序不能反。

今日思考题:你去公司第一天,写了一个文件处理的脚本,测试时一切正常。但用户反馈说:跑一会儿就报"Too many open files"错误。你猜这是什么问题?用今天学的异常处理思路,你会怎么改?

看完有收获的话,欢迎在评论区留下你的答案。我会挑几位同学的思路详细点评。如果觉得有用,转发给身边正在学Python的朋友一起看~

最新文章

随机文章