初识Python异常处理、模块与包

一、引言:让程序优雅地面对错误

在之前的博客中,我们学习了函数进阶和文件操作。程序运行时,我们总是假设一切"完美"------文件存在、类型正确、网络畅通。但现实世界充满了不确定性:用户可能删除了文件,网络可能突然断开,数据格式可能异常......

当这些"意外"发生时,Python会抛出异常(Exception) ,程序会崩溃并显示一堆红色的错误信息。这显然不是我们想要的结果。我们需要的是:当异常发生时,程序能够"优雅地"处理它,给出友好的提示,而不是直接崩溃

与此同时,当我们的项目越来越庞大,代码量越来越多时,如何高效地组织代码、复用功能?答案就是------模块(Module)包(Package)

本篇博客将系统讲解Python的异常处理模块导入包管理三大核心技能,让你写出更健壮、更易维护的程序。

二、Python异常处理

2.1 什么是异常?

异常是指程序运行时检测到的错误。当Python解释器遇到无法继续执行的错误时,就会抛出异常并停止运行。

python 复制代码
# 打开一个不存在的文件
f = open("xxx.txt", "r", encoding="utf-8")
# FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'

上面的例子中,FileNotFoundError就是一个异常。程序直接崩溃,后续代码无法执行。

2.2 为什么要捕获异常?

世界上没有完美的程序,任何程序运行时都可能出现异常。我们要做的是:对可能出现的错误提前做好准备,当异常发生时,有后续的应对手段

捕获异常可以让程序在出错时"优雅地降级",而不是"粗暴地崩溃"。

2.3 异常捕获的完整语法

Python提供了try-except结构来捕获和处理异常。

(1)捕获常规异常
python 复制代码
try:
    # 可能会发生错误的代码
    f = open("xxx.txt", "r", encoding="utf-8")
except:
    # 如果出现异常执行的代码
    print("文件不存在,已自动创建")
    f = open("xxx.txt", "w", encoding="utf-8")
(2)捕获指定异常

可以捕获指定类型的异常,并获取异常详情。

python 复制代码
try:
    print(name)          # NameError
except NameError as e:
    print("变量未定义")
    print(e)             # name 'name' is not defined
(3)捕获多个异常

使用元组可以同时捕获多种异常。

python 复制代码
try:
    print(name)          # NameError
    print(1 / 0)         # ZeroDivisionError
except (NameError, ZeroDivisionError) as e:
    print("出现变量未定义或除以零异常")
    print(e)
(4)捕获所有异常

Exception是所有异常的基类,可以捕获任何异常。

python 复制代码
try:
    print(name)
    print(1 / 0)
except Exception as e:
    print("程序出现异常")
    print(e)
(5)异常else

else表示没有异常时要执行的代码

python 复制代码
try:
    print("正常执行")
except Exception as e:
    print("出现异常")
else:
    print("没有异常,一切正常")
(6)异常finally

finally表示无论是否异常,都要执行的代码,常用于资源清理。

python 复制代码
try:
    f = open("test.txt", "r")
except Exception as e:
    print("文件打开失败")
finally:
    print("无论是否异常,我都会执行")
    # 可在此关闭文件等清理操作

2.4 异常的传递性

异常具有传递性:如果在函数A中发生异常且未被捕获,异常会向调用方传递------传递给函数B,再传递给main函数。如果所有函数都不处理,程序最终崩溃。

python 复制代码
def fun01():
    print("fun01开始")
    num = 1 / 0          # 这里发生异常
    print("fun01结束")

def fun02():
    print("fun02开始")
    fun01()              # 异常向上传递
    print("fun02结束")

def main():
    try:
        fun02()
    except Exception as e:
        print("捕获到异常:", e)

main()
# 输出:捕获到异常: division by zero

利用异常传递性的好处 :我们可以在程序入口(如main函数)统一捕获异常,确保无论何处发生异常,程序都不会崩溃。

三、Python模块

3.1 什么是模块

模块(Module) 是一个以.py结尾的Python文件。模块中可以定义函数、类、变量,也可以包含可执行代码。

简单来说:模块就是一个"工具包",里面封装了各种功能,我们可以导入并使用它们

Python内置了大量实用模块,如:

  • time:时间相关功能

  • random:随机数生成

  • os:操作系统交互

  • math:数学运算

3.2 模块的导入方式

(1)import 模块名

导入整个模块,使用时通过模块名.功能名()调用。

python 复制代码
import time

print("开始")
time.sleep(2)          # 调用time模块的sleep功能
print("结束")
(2)from 模块名 import 功能名

导入模块中的特定功能,使用时直接写功能名。

python 复制代码
from time import sleep

print("开始")
sleep(2)               # 不需要写 time.
print("结束")
(3)from 模块名 import *

导入模块的所有功能(不推荐,容易造成命名冲突)。

python 复制代码
from time import *

print(localtime())     # 直接使用time的所有功能
sleep(2)
(4)import 模块名 as 别名

给模块起别名,简化长名称。

python 复制代码
import time as t

t.sleep(2)             # 使用别名调用
print(t.localtime())
(5)from 模块名 import 功能名 as 别名

给导入的功能起别名。

python 复制代码
from time import sleep as s

s(2)                   # 使用别名调用

3.3 导入顺序建议

  1. 内置模块(如timeos

  2. 第三方模块(如numpypandas

  3. 自定义模块

3.4 自定义模块

我们可以创建自己的.py文件作为模块,供其他程序导入使用。

创建my_module1.py

python 复制代码
def test(a, b):
    print(f"my_module1 计算:{a} + {b} = {a + b}")

在另一个文件中导入使用:

python 复制代码
import my_module1

my_module1.test(3, 5)   # my_module1 计算:3 + 5 = 8

3.5 模块的__name__变量

每个模块都有一个__name__属性:

  • 当模块被直接运行 时,__name__的值为"__main__"

  • 当模块被导入 时,__name__的值为模块名

这个特性常用于编写"既可作为模块导入,又可独立运行"的代码:

python 复制代码
# my_module1.py
def test(a, b):
    print(f"计算结果:{a + b}")

if __name__ == "__main__":
    # 只有直接运行此文件时才执行
    test(1, 2)

3.6 __all__变量

在模块中定义__all__列表,可以控制from module import *时导出的内容。

python 复制代码
# my_module2.py
__all__ = ['test1', 'test2']   # 只允许导入test1和test2

def test1(a, b):
    print(a + b)

def test2(a, b):
    print(a * b)

def test3(a, b):
    print(a - b)

导入时,test3不会被导入。

四、Python包

4.1 什么是包?

当模块越来越多时,我们需要用**包(Package)**来组织管理它们。

包是一个包含__init__.py文件的文件夹,它可以包含多个模块文件。

python 复制代码
my_package/                # 包
    __init__.py            # 标识这是一个包
    my_module1.py          # 模块1
    my_module2.py          # 模块2
    my_module3.py          # 模块3

4.2 包的作用

  • 物理角度 :包是一个文件夹,包含__init__.py

  • 逻辑角度:包的本质依然是模块,用于组织功能相关的模块

4.3 导入包的方式

方式一:import 包名.模块名
python 复制代码
import my_package.my_module1

my_package.my_module1.info_print()
方式二:from 包名 import *

需要在__init__.py中配置__all__变量,控制允许导入的模块列表。

python 复制代码
# my_package/__init__.py
__all__ = ['my_module1', 'my_module2']
python 复制代码
from my_package import *

my_module1.info_print()
my_module2.info_print()

4.4 安装第三方包

Python拥有庞大的第三方生态,可通过pip工具安装。

python 复制代码
pip install 包名

常用国内镜像源:

  • 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/

  • 阿里云:http://mirrors.aliyun.com/pypi/simple/

指定镜像源安装:

python 复制代码
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple/

五、异常、模块与包的对比总结

概念 定义 作用 关键语法
异常 程序运行时的错误 处理错误,防止程序崩溃 try-except-else-finally
异常传递 异常向调用方逐级传递 在统一入口捕获异常 在main函数设置try-except
模块 .py文件 封装功能,实现代码复用 importfrom ... import
包含__init__.py的文件夹 组织管理多个模块 import 包.模块

六、综合实战:健壮的文件读取程序

综合运用异常处理、文件操作和模块知识,编写一个"安全读取文件"的程序:

python 复制代码
import os

def safe_read_file(filename):
    """
    安全地读取文件内容,若文件不存在则创建并返回空字符串
    """
    try:
        with open(filename, "r", encoding="utf-8") as f:
            content = f.read()
            return content
    except FileNotFoundError:
        print(f"文件 {filename} 不存在,已自动创建")
        # 创建空文件
        with open(filename, "w", encoding="utf-8") as f:
            f.write("")
        return ""
    except PermissionError:
        print(f"没有权限读取文件 {filename}")
        return None
    except Exception as e:
        print(f"读取文件时发生未知错误:{e}")
        return None

def main():
    filename = "data.txt"
    content = safe_read_file(filename)
    if content is not None:
        print(f"文件内容长度:{len(content)}")
    else:
        print("读取失败")

if __name__ == "__main__":
    main()

七、总结

本篇博客系统学习了三个重要的Python进阶概念:

主题 核心知识点
异常处理 try-except捕获异常、else无异常执行、finally总是执行、异常传递性
模块导入 五种导入方式、自定义模块、__name__变量、__all__控制
包管理 包的结构(含__init__.py)、包导入方式、第三方包安装

建议

  1. 永远不要忽略异常------即使不处理,也要记录下来

  2. 尽量捕获指定异常 ,而不是直接用Exception------更精确

  3. 利用异常传递性,在程序入口统一处理

  4. 模块名要简洁有意义,避免和内置模块冲突

  5. 使用**if __name__ == "__main__"**让模块兼具"可执行"和"可导入"两种能力

  6. 合理使用包组织代码,保持项目结构清晰

相关推荐
2601_962295331 小时前
Python自动化批量文档生成工具:Word与Excel的结合应用
python·自动化·word·excel·文档生成
2601_9622932410 小时前
Python自动化统计团队工作量并生成可视化仪表盘的脚本方案【指导】
python·数据分析·自动化·可视化·仪表盘
2601_9622937911 小时前
OCRmyPDF批处理脚本:使用Python自动化复杂OCR任务
python·自动化·批处理脚本·ocrmypdf·ocr任务
Java后端的Ai之路12 小时前
20、Python - 备忘录模式
开发语言·人工智能·python·外观模式·备忘录模式
2601_9620777113 小时前
基于Python与NLP的新闻事件信息抽取实战:从NER到时空标准化
python·nlp·transformers·spacy·新闻事件抽取
JavaPub-rodert13 小时前
LangChain 从入门到 Agent 实战:用 Python 搭建一个真正能调用工具和知识库的 AI 助手
人工智能·python·langchain
郝学胜-神的一滴13 小时前
Qt 高级编程 045:坐标体系深度实战
开发语言·c++·windows·python·qt·程序人生
m0_3807438714 小时前
给 OpenAI API 调用加上模型切换:GPT-5.1 和 Codex 的配置实践
人工智能·python·gpt
2601_9622974815 小时前
在python3中、下列输出变量a的正确写法是_2020超星大数据Python免费答案
数据结构·python·算法·编程·字符串操作