Python 的 try 语句(异常处理)详细介绍

Python 的 try 语句(异常处理)详细介绍

在 Python 中,try语句是异常处理(Error Handling) 的核心机制,用于捕获和处理程序运行过程中出现的错误(如语法错误之外的运行时错误:除零错误、索引越界、网络请求失败等),避免程序因错误直接崩溃,让程序具备更强的鲁棒性。(在编程领域,鲁棒性(Robustness) 指的是程序在面对异常、错误、非法输入或恶劣环境时,能够保持稳定运行而不崩溃,并且能合理处理这些异常情况的能力。简单来说,就是程序的 “抗造”“耐折腾” 程度。

一、异常的基本概念

异常是程序运行时发生的不正常情况(错误),比如:

ZeroDivisionError:除数为 0;IndexError:列表索引超出范围;KeyError:字典键不存在;requests.exceptions.RequestException:网络请求失败(如超时、连接拒绝);FileNotFoundError:文件不存在。

如果不处理这些异常,程序会直接终止并抛出错误信息;而try语句可以捕获这些异常,并执行自定义的处理逻辑。

二、try 语句的完整语法结构

Python 的try语句有多种组合形式,从简单到复杂依次为:try-excepttry-except-elsetry-except-finallytry-except-else-finally

1. 基础结构:try-except(核心)

这是最常用的形式,用于捕获并处理指定的异常

try: # 可能引发异常的代码块(受保护的代码) risky_code() except [异常类型1] [as 异常对象]: # 当异常类型1发生时,执行的处理逻辑 handle_exception1() except [异常类型2] [as 异常对象]: # 当异常类型2发生时,执行的处理逻辑 handle_exception2() except: # 捕获所有未被上面捕获的异常(兜底处理,不推荐滥用) handle_all_other_exceptions() 

关键说明

try块:存放可能出现异常的代码(如网络请求、文件操作、数据类型转换等)。except块:当try块中发生指定类型的异常时,执行该块的代码;可以有多个except块,分别处理不同类型的异常。as 异常对象:可选,用于获取异常的详细信息(如错误描述、堆栈信息),常用变量名:eerr

示例 1:捕获特定异常

try: a = 10 / 0 # 会引发ZeroDivisionError b = [1, 2, 3][5] # 会引发IndexError(但上面的错误先发生,这行不会执行) except ZeroDivisionError as e: print(f"错误:除数不能为0,异常信息:{e}") except IndexError as e: print(f"错误:索引越界,异常信息:{e}") 

输出:错误:除数不能为0,异常信息:division by zero

示例 2:捕获多个异常(简写)如果多个异常的处理逻辑相同,可以将它们放在一个except块中,用元组包裹:

try: data = {"name": "张三"} print(data["age"]) # KeyError # num = int("abc") # ValueError except (KeyError, ValueError) as e: print(f"发生了键错误或值错误:{e}") 

示例 3:兜底捕获所有异常(不推荐)使用无参数的except可以捕获所有异常,但会隐藏未知的错误,不利于调试,仅建议在程序顶层做兜底处理:

try: 10 / 0 except ZeroDivisionError as e: print(f"除数为0:{e}") except: print(f"发生了未知错误:{e}") # 兜底处理 
2. 扩展结构:try-except-else

try块中没有发生任何异常时,会执行else块的代码(else块是可选的)。

try: # 可能引发异常的代码 result = 10 / 2 except ZeroDivisionError as e: print(f"错误:{e}") else: # 无异常时执行的代码 print(f"计算结果:{result}") 

输出:计算结果:5.0

作用将 “正常逻辑” 和 “异常处理逻辑” 分离,代码结构更清晰(else块只执行正常情况的逻辑)。

仅当try块中的代码:正常执行完毕(没有引发任何异常);且没有被returnbreakcontinue等语句中断;才会执行else块的代码。如果try块中引发了异常:程序会立即跳转到对应的except块中执行异常处理逻辑;else块的代码会被完全跳过,不会执行。
3. 完整结构:try-except-finally

finally块中的代码无论是否发生异常,都会执行finally块是可选的),常用于释放资源(如关闭文件、关闭网络连接、释放锁等)。

try: # 可能引发异常的代码 f = open("test.txt", "r") content = f.read() except FileNotFoundError as e: print(f"错误:文件不存在,{e}") finally: # 无论是否异常,都会执行:关闭文件 if 'f' in locals() and not f.closed: f.close() print("文件已关闭") 

关键特性

即使try块中有returnbreakcontinue等语句,finally块仍会执行;常用于资源的清理工作,避免资源泄漏。
4. 终极结构:try-except-else-finally

整合所有部分,覆盖所有场景:

try: num = int(input("请输入一个整数:")) result = 10 / num except ValueError as e: print(f"错误:请输入有效的整数,{e}") except ZeroDivisionError as e: print(f"错误:除数不能为0,{e}") else: print(f"10 / {num} = {result}") finally: print("程序执行完毕(无论是否异常,都会显示)") 

三、异常对象的常用操作

通过as 异常对象可以获取异常的详细信息,常用操作:

直接打印异常对象:获取错误描述(如print(e));获取异常类型type(e)获取异常的堆栈信息:使用traceback模块(适合调试)。
import traceback try: 10 / 0 except Exception as e: # 打印错误描述 print(f"异常描述:{e}") # 打印异常类型 print(f"异常类型:{type(e)}") # 打印完整的堆栈信息(包含出错的行号、文件路径) print("堆栈信息:") traceback.print_exc() 

五、try 语句的使用场景(爬虫 / 开发常用)

1. 网络请求(处理网络异常)

爬虫中网络请求容易出现超时、连接拒绝、DNS 错误等异常,必须用try处理:

import requests HEADERS = {"User-Agent": "Mozilla/5.0"} url = "https://movie.douban.com/top250" try: response = requests.get(url, headers=HEADERS, timeout=10) response.raise_for_status() # 触发HTTP错误(如403、404、500) except requests.exceptions.Timeout as e: print(f"错误:请求超时,{e}") except requests.exceptions.HTTPError as e: print(f"错误:HTTP状态码异常,{e}") except requests.exceptions.RequestException as e: print(f"错误:网络请求失败,{e}") else: print(f"请求成功,状态码:{response.status_code}") 
2. 文件操作(处理文件不存在、权限错误)
try: with open("douban_top50.csv", "r", encoding="utf-8-sig") as f: content = f.read() except FileNotFoundError as e: print(f"错误:文件不存在,{e}") except PermissionError as e: print(f"错误:没有文件读取权限,{e}") except UnicodeDecodeError as e: print(f"错误:文件编码错误,{e}") else: print(f"文件读取成功,内容长度:{len(content)}") 
3. 数据解析(处理数据格式异常)

爬虫解析数据时,可能因网页结构变化导致标签不存在,需处理异常:

from bs4 import BeautifulSoup html = '<div><span>肖申克的救赎</span></div>' soup = BeautifulSoup(html, "html.parser") try: movie_name = soup.find("span", class_="title").text movie_score = soup.find("span", class_="rating_num").text # 该标签不存在,触发AttributeError except AttributeError as e: print(f"错误:标签不存在,{e}") movie_score = "未知" finally: print(f"电影名称:{movie_name},评分:{movie_score}") 

输出:错误:标签不存在,'NoneType' object has no attribute 'text'电影名称:肖申克的救赎,评分:未知

六、使用 try 的最佳实践

精准捕获异常:尽量捕获具体的异常类型(如ZeroDivisionError),避免使用无参数的except(兜底除外),否则会隐藏未知错误;保持 try 块最小化:只在try块中放入可能引发异常的代码,不要将无关代码放入,便于定位错误;使用 finally 释放资源:对于文件、网络连接、数据库连接等资源,务必在finally中释放,或使用上下文管理器(with语句,底层也是基于finally实现);异常信息要明确:处理异常时,打印清晰的错误信息(如异常类型、错误原因、发生位置),便于调试;避免过度使用异常:异常处理是为了处理不可预见的错误,不要用异常处理替代正常的逻辑判断(如不要用try-except判断列表是否为空,应直接用if not lst)。

七、与上下文管理器(with 语句)的结合

Python 中的with语句是异常处理的语法糖,常用于资源管理(如文件、网络连接),它会自动在代码块结束后释放资源,即使发生异常也不例外(底层调用了__enter____exit__方法,__exit__中包含了finally的逻辑)。

示例:用 with 语句简化文件操作(替代 try-finally)

# 无需手动关闭文件,with语句会自动处理 try: with open("test.txt", "r") as f: content = f.read() except FileNotFoundError as e: print(f"错误:文件不存在,{e}") else: print(f"文件内容:{content}") 

总结

        Python 的try语句是处理运行时异常的核心工具,通过try-except捕获异常、else执行正常逻辑、finally释放资源,能让程序在面对错误时更健壮。在爬虫、文件操作、数据处理等场景中,合理使用try语句是编写生产级代码的必备技能。同时,遵循精准捕获、最小化 try 块、明确异常信息等最佳实践,能让异常处理代码更优雅、更易维护。

Read more

【C + + 】一文吃透 C++ 智能指针:RAII 思想 + 三大指针 + 实战避坑

【C + + 】一文吃透 C++ 智能指针:RAII 思想 + 三大指针 + 实战避坑

🌟个人主页:第七序章   🌈专栏系列:C++ 目录 ❄️前言: ☀️一、智能指针的使用 ☀️二、RAII和智能指针 ⭐RAII思想 ⭐智能指针思想 ☀️三、C++标准库中智能指针的使用 ⭐auto_ptr ⭐unique_ptr ⭐shared_ptr ⭐删除器 ☀️四、智能指针的实现原理 ⭐share_ptr实现原理 ⭐构造函数 ⭐拷贝构造 ⭐拷贝赋值 ⭐析构函数 ⭐删除器 ☀️五、shared_ptr循环引用问题 ⭐weak_ptr解决循环引用问题 ⭐weak_ptr ☀️ 六、智能指针总结 ☀️七、内存泄漏详解与防范 ⭐内存泄漏是什么?为什么危险? ⭐典型的内存泄漏场景分析 ⭐常见内存泄漏类型分类 ⭐内存泄漏检测工具一览 ⭐如何高效避免内存泄漏? ☀️九、shared_

By Ne0inhk

【C++26静态反射元编程实战】:掌握下一代C++黑科技的5大核心技巧

第一章:C++26静态反射元编程概述 C++26 正在将静态反射(Static Reflection)作为核心语言特性之一引入,旨在为开发者提供在编译期获取和操作类型信息的能力,而无需依赖复杂的模板元编程技巧。这一机制允许程序在不运行时开销的前提下,分析类、结构体、函数等实体的结构,从而实现高度通用的序列化、ORM 映射、配置解析等功能。 静态反射的核心理念 静态反射通过新的关键字和标准库设施,如 reflect 和 meta,使编译器能在编译期间暴露类型的元数据。这些元数据可被用于生成代码或执行条件判断,提升类型安全与性能。 基本语法与使用示例 #include <reflect> struct Person { std::string name; int age; }; // 获取Person类型的编译期元对象 constexpr auto meta_person = reflect(Person); // 遍历所有字段名称(假定C++26支持此语法)

By Ne0inhk
墨色规则与血色节点:C++红黑树设计与实现探秘

墨色规则与血色节点:C++红黑树设计与实现探秘

前言     前几天攻克了AVL树,我们已然是平衡二叉树的强者。但旅程还未结束,下一个等待我们的,是更强大、也更传奇的**终极BOSS**——红黑树。它不仅是map和set的强大心脏,更是C++ STL皇冠上的明珠。准备好了吗?让我们一起揭开它的神秘面纱。 1.红黑树的概念 1.1.红黑树是什么     红黑树是一科二叉搜索树,他的每个节点增加一个存储为代表着该节点的颜色,和它的名字一样,节点的颜色可以是红色或者是黑色。通过对任何一条根到叶子的路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是接近平衡的。     红黑树是被很多条规则进行束缚的二叉搜索树,通过这些规则,可以保证红黑树没有一条路径会比其他路径长出2倍,并且保持其相对平衡,下面我来讲述一下这些规则。 1.2.红黑树的规则     1.每个节点不是黑色的就是红色的(这肯定,不然不会被叫做红黑树了)。     2.根节点必须是黑色的     3.如果一个节点是红色的,则它的两个孩子节点必须是黑色的,也就是说任意一条路径上并不会出现连续的红色的节点。     4.对于任意的一个

By Ne0inhk
C++ 虚函数与纯虚函数:多态的核心实现基石

C++ 虚函数与纯虚函数:多态的核心实现基石

C++ 虚函数与纯虚函数:多态的核心实现基石 💡 学习目标:深度理解虚函数与纯虚函数的本质区别,掌握虚函数表的底层原理,能够灵活运用二者设计具备多态特性的类结构。 💡 学习重点:虚函数的声明与重写规则、纯虚函数与抽象类的使用场景、虚函数表的工作机制、虚函数的常见陷阱与解决方案。 一、虚函数的本质与定义 ✅ 结论:虚函数是 C++ 实现动态多态的核心,通过在基类成员函数前添加 virtual 关键字,允许派生类重写该函数,并在运行时根据对象的实际类型调用对应版本。 1.1 虚函数的声明语法 虚函数的声明必须在基类中进行,语法格式如下: class 基类名 {public:virtual 返回值类型 函数名(参数列表){// 函数体}}; 1.2 虚函数的核心特性 1. 运行时绑定:函数调用关系在程序运行时确定,而非编译时。 2. 重写规则:派生类重写的函数必须与基类虚函数的函数名、参数列表、返回值类型完全一致(协变类型除外)。 3.

By Ne0inhk