当前位置:首页>python>《Python 从入门到精通》067|try.except 基础:让程序学会优雅报错

《Python 从入门到精通》067|try.except 基础:让程序学会优雅报错

  • 2026-10-11 07:29:58
《Python 从入门到精通》067|try.except 基础:让程序学会优雅报错

上一章我们已经认识了异常,知道了程序为什么会在运行过程中突然报错、突然中断。现在问题来了。

如果程序一出错就直接停掉,那很多场景其实是很难用的。

比如用户输错了一个年龄,程序就整个结束。 比如文件一时没找到,后面的流程全都停下。 比如数据里混进了一条坏记录,整个批处理任务全部报废。

这时候,就需要 try...except 出场了。

它的作用,不是让错误凭空消失,而是让程序在遇到异常时,不要那么狼狈地崩掉,而是按你设计好的方式去处理问题。

说得直白一点,try...except 就是在告诉程序:

我知道这里有可能出错。 如果真的出错了,不要立刻翻车。 先按我的规则处理一下。

这就是所谓的优雅报错。

一、为什么一定要学 try...except

很多新手刚接触异常处理时,会有一种想法:

既然代码会报错,那我小心一点写不就行了,为什么还要专门学异常处理。

这个想法只对了一半。

小心写代码当然很重要,但现实世界不会永远配合你。 用户可能输错内容。 文件可能临时缺失。 网络可能突然断开。 某条数据可能格式不对。

你不能要求所有输入永远正确,也不能保证所有环境永远稳定。 所以真正成熟的程序,不只是能在理想情况下跑通,还要能在出问题时不至于完全失控。

try...except 的价值,就在这里。

它不是帮你逃避错误,而是帮你接住错误。

二、先看最基本的写法

最简单的结构如下:

try:    可能出错的代码except:    出错后执行的代码

先不要急着背,先把它翻译成人话。

try 的意思是:先试试看。except 的意思是:如果试的时候出错了,就执行这里的处理逻辑。

看一个最简单的例子:

try:    print(10 / 0)except:    print('程序出错了')

运行后,程序不会像以前那样直接抛出一大段报错然后停掉,而是会输出:

程序出错了

这就说明,异常被接住了。

前面那个除以 0 的错误,确实还是发生了。 只不过这次程序没有把错误直接甩到你脸上,而是按照 except 里的逻辑做了处理。

三、你要真正理解的,不是语法,而是控制流程

很多人看到 try...except,只记住了写法,却没理解它到底改变了什么。

它改变的,是程序出错时的走向。

没有 try...except 的时候,程序一旦遇到异常,通常就直接停掉。 有了 try...except 以后,程序遇到异常时,可以先跳到 except 里执行处理逻辑。

也就是说,它给了程序一个备用方案。

正常情况下,程序按主流程走。 出错情况下,程序切到异常处理流程。

你可以把它想成开车时的应急方案。 平时路况正常,就按原路线开。 一旦前方封路,就走备用路线。try...except 干的,就是这件事。

四、try 里到底该放什么

这点非常重要。

try 里放的,应该是你判断为有可能出错的代码。 不是整份程序一股脑全塞进去,也不是为了图省事把几十行都包起来。

比如:

age_text = input('请输入年龄:')try:    age = int(age_text)    print(age + 1)except:    print('你输入的年龄格式不对')

这里最可能出问题的点,就是 int(age_text)。 因为如果用户输入的是数字,没事。 如果输入的是别的内容,比如中文或者字母,就可能报错。

所以把这一段放进 try,就很自然。

异常处理的第一原则,其实就是:

只包住你真正担心会出错的那部分。

这样代码会更清楚,后面定位问题也更方便。

五、一个特别常见的实际场景:处理用户输入

下面这个例子,几乎每个初学者都应该亲手写一遍。

age_text = input('请输入你的年龄:')try:    age = int(age_text)    print('明年你的年龄是:', age + 1)except:    print('输入有误,请输入数字')

如果用户输入:

18

程序会输出:

明年你的年龄是: 19

如果用户输入:

十八

程序则不会崩掉,而是输出:

输入有误,请输入数字

这就是 try...except 最直观的价值。

它不是让错误变没,而是让程序在错误出现时,还能给出更友好的反馈。

这件事对用户体验非常重要。 因为用户不关心你内部报了什么 ValueError,他只想知道自己下一步该怎么做。

六、except 为什么不能只理解成报个提示

很多人刚学到这里,会觉得 except 不就是打印一句提示吗。其实远不止。

except 里可以做很多事,比如:

提示用户重新输入 记录日志 跳过这次错误继续处理下一条数据 给出默认值 结束当前操作但不中断整个程序

也就是说,except 不是一个单纯的报错显示区,而是一个真正的异常处理区。

看一个稍微实用一点的例子:

scores = ['90', '85', 'abc', '88']for item in scores:try:        score = int(item)        print('成绩是:', score)except:        print('发现一条无效成绩,已跳过:', item)

输出结果会是:

成绩是: 90成绩是: 85发现一条无效成绩,已跳过: abc成绩是: 88

如果没有 try...except,程序处理到 abc 这里就会直接停。 但现在程序能跳过这条坏数据,继续处理后面的内容。

这已经非常接近真实开发场景了。

七、异常处理不是掩盖问题,而是有意识地处理问题

这里一定要避免一个误区。

有些人学了 try...except 以后,看到哪都想套一个,仿佛这样代码就安全了。其实不是。

如果你只是机械地把错误包住,却不关心为什么错、错了以后怎么处理,那就不叫异常处理,只能算把问题藏起来。

比如这段代码:

try:    result = 10 / 0except:pass

程序确实不会报错了。 但这段代码的问题在于,错误发生了,你却什么都没做。 程序表面安静,内部其实已经出了问题。

所以要记住:

异常处理的重点不是别报错,而是报错以后怎么办。

如果你接住了异常,却没有合理处理,那很多时候只是让问题更隐蔽。

八、为什么正式代码不推荐直接写裸 except

刚才为了帮助你入门,我们用了最简单的写法:

try:    ...except:    ...

这种写法能用,但不是最推荐的方式。 因为它会把所有异常一股脑接住。

更常见、更规范的写法,是指定异常类型。

比如:

try:    age = int(input('请输入年龄:'))    print(age + 1)except ValueError:    print('输入格式不正确,请输入数字')

这里的意思是:

如果这里发生的是 ValueError,就执行下面的处理逻辑。

为什么这样更好?

因为不同异常,代表的问题不同。 你只处理你真正预期到的那种异常,代码会更准确,也更安全。

比如用户输入年龄时,最常见的问题就是数字转换失败。 这时捕获 ValueError 就很合理。

这就像医生看病一样。 你不能不管什么情况都开同一种药。 得先知道是哪类问题,再做对应处理。

九、最常见的几个异常类型,要开始慢慢认识了

在 try...except 里,你以后会很常见到这些类型:

ValueError值的形式不对。比如把一段不是数字的文本转成整数。

TypeError类型不支持当前操作。比如字符串和整数直接相加。

IndexError列表下标越界。

KeyError字典里没有对应的键。

FileNotFoundError文件不存在。

你现在还是不用死背,但从这一章开始,要慢慢形成一个意识:

异常不仅有报错这个动作,还有具体类型。

而异常类型,往往决定你该怎么处理它。

十、文件处理里 try...except 特别常用

前面我们学文件时,已经见过一种高频风险:文件不存在。

比如:

with open('data.txt', 'r', encoding='utf-8') as f:    content = f.read()    print(content)

如果 data.txt 不存在,程序就会直接报错。

现在我们可以给它加上异常处理:

try:with open('data.txt', 'r', encoding='utf-8') as f:        content = f.read()        print(content)except FileNotFoundError:    print('文件不存在,请检查文件名或路径')

这样一来,程序就不会因为文件没找到而直接崩掉,而是会给出更清晰的提示。

这个例子特别有代表性。 因为它说明,异常处理不只是给用户输入兜底,也是在给外部环境兜底。

十一、try 成功时,except 会不会执行

不会。

这一点你必须非常清楚。

try 里的代码如果顺利执行,没有发生异常,那么 except 就会被跳过。

比如:

try:    print(10 / 2)except:    print('出错了')

输出结果是:

5.0

这里不会打印出错了。 因为根本没出错。

所以 try...except 并不是二选一硬执行,而是根据运行情况动态分流:

没出错,走 try 的正常流程。 出错了,跳去 except 的异常流程。

这就是它的本质。

十二、try 里一旦某行出错,后面会怎么样

这个问题特别关键。

看下面这段代码:

try:    print('开始执行')    num = int('abc')    print('这行还能执行吗')except ValueError:    print('发生了值错误')

输出会是:

开始执行发生了值错误

中间那句:

print('这行还能执行吗')

不会执行。

原因很简单。try 代码块一旦某一行触发异常,当前这个 try 里后面的代码通常就不继续走了,而是直接跳到匹配的 except。

这点你一定要想明白。 因为它会影响你如何组织代码结构。

也就是说,try 不是说里面每一行都一定跑完。 它是试着往下执行,一旦撞上异常,就立刻切去异常处理分支。

十三、一个很典型的小案例:让用户反复输入直到正确

虽然这一章重点是 try...except 基础,但我们可以先看一个很实用的简单组合。

whileTrue:    text = input('请输入一个整数:')try:        num = int(text)        print('你输入的整数是:', num)breakexcept ValueError:        print('输入无效,请重新输入')

这段代码的意思是:

用户输入内容 程序尝试转成整数 如果成功,就打印并结束循环 如果失败,就提示重新输入

这就是异常处理和循环配合的经典用法。

现实里很多输入场景,都会这么写。 因为你无法保证用户第一次就输入正确,但你可以让程序有能力温和地引导他继续输入。

这比程序一报错就退出,要强太多了。

十四、别把所有逻辑都塞进 try

这是一个特别需要提前提醒的习惯问题。

有些初学者喜欢这样写:

try:    text = input('请输入数字:')    num = int(text)    result = 100 / num    print(result)except:    print('出错了')

这段代码不是不能跑,但问题在于,它把多个可能出错的点全混在一起了。

到底是输入转换失败了。 还是除数变成了 0。 还是别的问题。

你用一句笼统的出错了,很难判断具体原因。

更清晰的思路是:

把可能出错的点拆开想。 预期什么错误,就尽量明确处理什么错误。

也就是说,异常处理写得好不好,不只是技术问题,也是代码表达能力的问题。

十五、try...except 的第一层价值,是让程序更友好

这一章你先不要把它想得太复杂。

在入门阶段,try...except 最直接的价值,就是让程序在出错时别那么生硬。

以前程序一错就是一大段报错。 现在你可以把它变成一句人能看懂的话。

比如:

请输入正确的数字 文件没有找到,请检查路径 这条数据格式不对,已跳过

这种变化看起来简单,但本质上已经是在从写给自己看的代码,往写给别人用的程序迈进了。

真正的程序,不只是自己能跑,更要让别人用起来不难受。

十六、第二层价值,是让程序更有韧性

除了更友好,try...except 还有一个非常重要的价值,就是让程序更能扛事。

比如批量处理 1000 条数据。 如果第 237 条脏了,难道前面 236 条和后面几百条都不要了?

显然不合理。

所以很多时候,我们会希望:

这一条错了,记下来,跳过。 后面的继续处理。

这就是异常处理让程序拥有的韧性。 它不再是一碰就碎,而是出现局部问题时还能维持整体运行。

虽然你现在还在学基础,但这个思维从现在开始建立,非常重要。

十七、一个文件读取的小练习案例

下面这段代码,建议你自己动手跑一下。

filename = input('请输入要读取的文件名:')try:with open(filename, 'r', encoding='utf-8') as f:        content = f.read()        print('文件内容如下:')        print(content)except FileNotFoundError:    print('文件不存在,请重新检查文件名')

这个例子很适合入门,因为它同时练到了三件事:

用户输入 文件读取 异常处理

如果文件存在,就正常读取。 如果文件不存在,就给出提示。

这已经很像一个真正能和用户交互的小工具了。

十八、本章你最该建立的意识

到这里,你一定要真正记住下面这句话:

异常处理不是为了假装程序没错,而是为了让程序在出错时仍然有控制感。

控制感这个词很重要。

没有 try...except 时,程序一旦报错,控制权就丢了。 有了它以后,程序至少还能按你的规则来响应问题。

你决定提示什么。 你决定是否跳过。 你决定是否继续。 你决定是否结束。

这就是程序从脆弱走向可靠的第一步。

十九、本章小练习

你可以立刻做两个练习。

练习 1 让用户输入一个数字,并输出 100 除以这个数字的结果。 如果用户输入的不是数字,就提示输入错误。

练习 2 让用户输入一个文件名,并尝试读取。 如果文件不存在,就提示文件没找到。

参考代码如下:

text = input('请输入一个数字:')try:    num = int(text)    print(100 / num)except ValueError:    print('输入的不是有效整数')except ZeroDivisionError:    print('不能输入 0')

再看文件版:

filename = input('请输入文件名:')try:with open(filename, 'r', encoding='utf-8') as f:        print(f.read())except FileNotFoundError:    print('没有找到这个文件')

这两个练习非常经典。 你把它们真正敲一遍,try...except 的基本感觉就建立起来了。

二十、本章总结

这一章,我们正式进入了异常处理的核心入口。

try 表示先尝试执行一段可能出错的代码。except 表示一旦发生异常,就执行对应的处理逻辑。 它不会让错误消失,但能让程序避免直接崩掉。 异常处理不是掩盖问题,而是更有意识地处理问题。 实际开发中,更推荐捕获明确的异常类型,而不是一股脑使用裸 except。try...except 最重要的价值,一是让程序对用户更友好,二是让程序在出错时更有韧性。

下一章我们继续往前走,把异常处理结构补完整:else 和 finally:异常处理的完整结构。

最新文章

随机文章