Python 模块与包完全指南 - 从 import 到自定义模块的代码组织利器
📝 摘要
Python 模块与包用于组织代码,通过 import 导入模块、自定义模块与包实现代码复用与结构管理。掌握模块与包,可提高项目可维护性与可扩展性。
🎯 前置知识点
基础知识点(必须掌握)
- Python 基础语法:了解变量、函数、类的基本用法
- 文件操作:理解 Python 文件的基本概念
- 目录结构:理解文件夹和文件的关系
进阶知识点(建议了解)
- 命名空间:理解 Python 的命名空间概念
- 模块搜索路径:了解 Python 如何查找模块
- 循环导入:理解模块间相互导入的问题
学习建议
- 小白(零基础):先理解模块和包的基本概念,掌握简单的 import 导入
- 初级(刚入门不久):学会创建自定义模块和简单的包结构
- 中级(入门一段时间):掌握相对导入、绝对导入和包的高级用法
- 高级(资深开发者):深入理解模块搜索机制,掌握项目级别的包结构设计
🔍 什么是模块和包?
核心概念
模块(Module):一个包含 Python 代码的 .py 文件,可以定义函数、类和变量。
包(Package):一个包含多个模块的目录,必须包含 __init__.py 文件,用于组织相关的模块。
生活化比喻:
- 模块:像一个工具箱文件,里面有锤子(函数)、扳手(类)、螺丝(变量)
- 包:像一个工具仓库,里面有多个工具箱文件,按照功能分类存放
为什么需要模块和包?
❌ 把所有代码写在一个文件中
问题场景:一个项目有 1000 行代码,全部写在一个文件里
问题:
# main.py(1000 行代码)
def function1(): ...
def function2(): ...
def function3(): ...
class Class1: ...
class Class2: ...
# ... 难以维护、查找困难
问题:
- 代码混乱,难以维护
- 查找困难,定位问题慢
- 无法复用代码
- 多人协作容易冲突
✅ 使用模块和包的解决方案
my_project/
├── main.py
├── utils.py # 工具函数模块
├── models.py # 数据模型模块
└── my_package/ # 包目录
├── __init__.py
├── module1.py
└── module2.py
优势:
- 代码组织清晰
- 易于维护和查找
- 便于代码复用
- 支持多人协作
📦 快速开始:创建第一个模块(完整项目示例)
🔥 完整项目结构(必须实现)
my_project/
├── utils.py # 工具模块(自己创建)
└── main.py # 主程序(自己创建)
生活化比喻:项目结构就像一个小型公司,utils.py 是后勤部门(提供工具),main.py 是总经理办公室(使用工具办事)。
学习目标
- 创建自己的模块(utils.py)
- 在另一个文件中导入并使用模块
- 理解模块的基本用法
- 掌握运行程序的方法
步骤 1:创建 utils.py 模块
文件路径:utils.py
# utils.py
# 这是一个自定义模块文件
# 🔥 重要!必须创建这个文件
def greet(name):
# def 作用:定义函数
# greet 作用:函数名(打招呼)
# name 作用:参数(要打招呼的人的名字)
return f"Hello, {name}!"
# return 作用:返回结果
# f"Hello, {name}!" 作用:格式化字符串,插入名字
def add(a, b):
# def 作用:定义函数
# add 作用:函数名(加法)
# a, b 作用:两个参数(要相加的数字)
return a + b
# return 作用:返回两个数字的和
def multiply(x, y):
# def 作用:定义函数
# multiply 作用:函数名(乘法)
# x, y 作用:两个参数(要相乘的数字)
return x * y
# return 作用:返回两个数字的乘积
为什么重要:
- 理解模块本质:掌握自定义模块的基本结构
- 学会函数定义:理解如何在模块中定义和返回函数
- 实践模块化思维:将相关功能组织成一个模块
步骤 2:创建 main.py 使用模块
文件路径:main.py(和 utils.py 在同一目录)
# main.py
# 🔥 重要!必须创建这个文件
# 这是主程序,用于使用 utils 模块
import utils
# import 作用:导入模块
# utils 作用:导入自定义的 utils 模块(同一目录下的 utils.py 文件)
message = utils.greet("张三")
# utils.greet 作用:调用 utils 模块中的 greet 函数
# "张三" 作用:传递给函数的参数(要打招呼的人)
# message 作用:接收函数返回的结果
print(message) # 输出:Hello, 张三!
result = utils.add(3, 5)
# utils.add 作用:调用 utils 模块中的 add 函数
# 3, 5 作用:两个要相加的数字
# result 作用:接收函数返回的结果
print(result) # 输出:8
为什么重要:
- 理解模块使用:掌握如何导入和使用自定义模块
- 学会函数调用:理解如何通过模块名调用模块中的函数
- 实践完整流程:体验从创建模块到导入使用的完整过程
运行方法:
方法一:使用 IDE 运行(推荐)
- PyCharm:右键
main.py文件 → 选择"Run 'main'" - VS Code:点击右上角的运行按钮 ▶️
- 或者在代码中按快捷键
Ctrl + Shift + F10(PyCharm)或F5(VS Code)
方法二:使用终端运行
- 打开终端(PowerShell 或 CMD)
- 进入项目目录:
cd my_project - 运行程序:
python main.py - 查看输出结果
生活化比喻:IDE 运行就像点外卖(点击按钮就送餐),终端运行就像自己做饭(需要开火、翻炒)。
📁 快速开始:创建第一个包(完整项目示例)
🔥 完整项目结构(必须实现)
my_project/
├── main.py # 主程序(自己创建)
└── my_package/ # 包目录(自己创建文件夹)
├── __init__.py # 包标识文件(必须创建)
├── module1.py # 模块 1:数据库操作(必须创建)
└── module2.py # 模块 2:文件操作(必须创建)
生活化比喻:项目结构就像一个小型商店,my_package 是仓库(放货),__init__.py 是仓库门牌(标识),module1.py 和 module2.py 是仓库里的工具箱,main.py 是总经理(使用仓库里的工具)。
学习目标
- 创建包目录和 init.py 文件
- 创建包中的模块(module1.py、module2.py)
- 在主程序中使用包中的模块
- 理解包的基本结构和用法
步骤 1:创建包目录
操作方式:
- 在
my_project文件夹中右键 → 新建文件夹 - 输入文件夹名称:
my_package
生活化比喻:创建一个新的文件夹,就像创建一个新的抽屉来存放工具。
步骤 2:创建 __init__.py 文件
Python 3.3+ 版本说明:
- Python 3.3 之前:必须有
__init__.py文件 - Python 3.3 之后:不是必须的,但仍推荐使用
推荐使用 __init__.py 的原因:
- 向后兼容:支持 Python 3.3 之前的版本
- 包的初始化:可以执行包的初始化代码
- 明确标识:明确标识目录是一个包,代码更清晰
- 控制导入:可以控制
from package import *的行为
# my_package/__init__.py
# __init__.py 作用:标识这个目录是一个包(推荐有,但不是必须)
# 可以导入包中的模块
from . import module1
from . import module2
# from . 作用:从当前目录导入
# import module1 作用:导入 module1 模块
# . 表示当前包目录
逐行代码解释:
- from . import module1:从当前包目录导入 module1 模块
- . 作用:表示当前包目录(相对导入)
- import module1:导入 module1 模块
- from . import module2:从当前包目录导入 module2 模块
生活化解释:这个文件就像仓库的门牌,告诉 Python 这是一个包,并可以在这里导入其他模块。
没有 __init__.py 的情况:
# Python 3.3+ 版本支持
# 即使没有 __init__.py,目录也可以作为包使用
# 这种包称为"命名空间包"
对比表格:
| 特性 | 有 init.py | 没有 init.py |
|---|---|---|
| Python 3.3 之前 | 必须 | 不支持 |
| Python 3.3+ | 推荐 | 支持(命名空间包) |
| 包的初始化 | 可以执行初始化代码 | 不能执行初始化代码 |
| 明确性 | 代码更清晰 | 可能混淆 |
| 向后兼容 | 完全兼容 | 不兼容旧版本 |
| 推荐使用场景 | 大多数情况 | 插件系统、分布式包 |
步骤 3:创建 module1.py 模块
文件路径:my_package/module1.py
# my_package/module1.py
# 这是一个数据库操作模块
# 🔥 重要!必须创建这个文件
def connect_database():
# def 作用:定义函数
# connect_database 作用:函数名(连接数据库)
return "数据库连接成功"
# return 作用:返回连接成功的消息
def query_data():
# def 作用:定义函数
# query_data 作用:函数名(查询数据)
return "查询到 10 条数据"
# return 作用:返回查询结果
为什么重要:
- 理解模块结构:掌握如何创建自定义模块
- 学会函数定义:理解如何在模块中定义函数
- 实践模块导入:后续可以通过 import 导入并使用这些函数
步骤 4:创建 module2.py 模块
文件路径:my_package/module2.py
# my_package/module2.py
# 这是一个文件操作模块
# 🔥 重要!必须创建这个文件
def read_file(filename):
# def 作用:定义函数
# read_file 作用:函数名(读取文件)
# filename 作用:参数(文件名)
return f"读取文件:{filename}"
# return 作用:返回读取文件的消息
def write_file(filename, content):
# def 作用:定义函数
# write_file 作用:函数名(写入文件)
# filename, content 作用:两个参数(文件名和内容)
return f"写入文件:{filename},内容:{content}"
# return 作用:返回写入文件的消息
为什么重要:
- 理解模块结构:掌握如何在包中创建多个模块
- 学会包组织:理解如何组织包中的模块
- 实践包的使用:后续可以导入包并使用包中的模块
步骤 5:创建 main.py 使用包
文件路径:main.py(和 my_package 在同一目录)
# main.py
# 🔥 重要!必须创建这个文件
# 这是主程序,用于使用 my_package 包
import my_package.module1 as db
# import 作用:导入包中的模块
# my_package.module1 作用:导入 my_package 包中的 module1 模块
# as db 作用:给模块起一个别名 db,方便使用
import my_package.module2 as file_op
# import 作用:导入包中的模块
# my_package.module2 作用:导入 my_package 包中的 module2 模块
# as file_op 作用:给模块起一个别名 file_op,方便使用
# 使用包中的模块
result1 = db.connect_database()
# db.connect_database 作用:调用数据库模块中的函数
print(result1) # 输出:数据库连接成功
result2 = file_op.read_file("data.txt")
# file_op.read_file 作用:调用文件操作模块中的函数
print(result2) # 输出:读取文件:data.txt
为什么重要:
- 理解包的使用:掌握如何导入和使用包中的模块
- 学会别名使用:理解如何使用 as 给模块起别名
- 实践完整流程:体验从创建包到导入使用的完整过程
运行方法:
方法一:使用 IDE 运行(推荐)
- PyCharm:右键
main.py文件 → 选择"Run 'main'" - VS Code:点击右上角的运行按钮 ▶️
- 或者在代码中按快捷键
Ctrl + Shift + F10(PyCharm)或F5(VS Code)
方法二:使用终端运行
- 打开终端(PowerShell 或 CMD)
- 进入项目目录:
cd my_project - 运行程序:
python main.py - 查看输出结果
生活化比喻:IDE 运行就像点外卖(点击按钮就送餐),终端运行就像自己做饭(需要开火、翻炒)。
📖 深入学习:init.py 完全指南
🔥 init.py 是什么?
init.py 是一个特殊的 Python 文件,它告诉 Python 这个目录是一个包。
生活化比喻:
- 没有 init.py:文件夹只是普通文件夹,Python 不认识它
- 有了 init.py:文件夹变成"包",Python 可以导入它
init.py 的四种用法
用法一:基本用法 - 标识包
# my_package/__init__.py
# 这是最基本的用法:创建一个空文件即可
# 文件内容可以为空,或者只写注释
为什么重要:
- 标识包:告诉 Python 这是一个包
- 向后兼容:支持 Python 3.3 之前的版本
用法二:导入包中的模块
# my_package/__init__.py
# 🔥 推荐:在 __init__.py 中导入包中的模块
from . import module1
from . import module2
# 这样,使用包时更简洁
# import my_package
# my_package.module1 # 可以直接使用
为什么重要:
- 简化导入:用户不需要知道包的内部结构
- 方便使用:可以从包直接访问模块
用法三:定义包的公共接口(all)
# my_package/__init__.py
# 🔥 重要:使用 __all__ 控制包的公共接口
from . import module1
from . import module2
# 定义公共接口
__all__ = ['module1', 'module2']
# __all__ 作用:控制 from my_package import * 时导入的内容
# 使用示例:
# from my_package import * # 只会导入 module1 和 module2
为什么重要:
- 控制访问:决定哪些模块可以被导入
- 隐藏内部实现:只暴露需要的内容
- 防止命名污染:避免导入不必要的模块
生活化比喻:all 就像酒店的前台,控制谁能进入(哪些模块),谁不能进入。
用法四:定义包级别的变量和函数
# my_package/__init__.py
# 🔥 高级用法:定义包级别的变量和函数
# 定义包版本
PACKAGE_VERSION = "1.0.0"
# 定义包级别的函数
def get_version():
return PACKAGE_VERSION
def info():
return "这是我的包"
# 使用示例:
# import my_package
# print(my_package.PACKAGE_VERSION) # 输出:1.0.0
# print(my_package.get_version()) # 输出:1.0.0
为什么重要:
- 包级别信息:提供包的元信息(版本、作者等)
- 统一接口:提供包级别的服务函数
- 方便调用:可以在任何地方通过包名访问
生活化比喻:包级别变量和函数就像仓库的公告栏和前台服务,提供统一的服务。
用法五:执行包的初始化代码
# my_package/__init__.py
# 🔥 高级用法:在包被导入时执行初始化代码
print("my_package 包正在初始化...")
# 可以执行任何初始化操作
import logging
logging.basicConfig(level=logging.INFO)
# 包级别的配置
CONFIG = {
'debug': False,
'timeout': 30
}
print("my_package 包初始化完成!")
# 使用示例:
# import my_package
# 输出:
# my_package 包正在初始化...
# my_package 包初始化完成!
为什么重要:
- 自动初始化:包被导入时自动执行
- 设置环境:配置日志、连接数据库等
- 一次性操作:只需要执行一次的初始化代码
生活化比喻:初始化代码就像包启动时的准备工作,就像开店前的准备(开灯、摆桌椅)。
完整示例:init.py 的高级用法
# my_package/__init__.py
# 🔥 完整示例:__init__.py 的高级用法
# 1. 导入包中的模块
from . import database
from . import query
# 2. 定义包的公共接口
__all__ = ['database', 'query', 'get_version', 'CONFIG']
# 3. 定义包级别的变量
PACKAGE_VERSION = "1.0.0"
PACKAGE_AUTHOR = "郑恩赐"
# 4. 定义包级别的函数
def get_version():
"""获取包版本"""
return PACKAGE_VERSION
def get_author():
"""获取包作者"""
return PACKAGE_AUTHOR
# 5. 执行初始化代码
print(f"my_package {PACKAGE_VERSION} 已加载")
# 使用示例:
# import my_package
# from my_package import database
# print(my_package.get_version()) # 输出:1.0.0
# database.connect()
为什么重要:
- 全面掌握:理解 init.py 的所有用法
- 实用性强:可以在实际项目中直接使用
- 最佳实践:展示 init.py 的正确使用方式
init.py 与命名空间包的区别
| 特性 | 有 init.py | 没有 init.py(命名空间包) |
|---|---|---|
| Python 版本 | 所有版本支持 | Python 3.3+ |
| 包的初始化 | 可以执行初始化代码 | 不能执行初始化代码 |
| 明确性 | 明确标识包 | 隐式包 |
| 向后兼容 | 完全兼容 | 不兼容旧版本 |
| 推荐使用 | 大多数情况 | 插件系统、分布式包 |
📖 深入学习:导入方式详解
导入方式对比
# 🔥 重要!建议手写实现这段代码,理解完整的模块导入语法
import my_package.module1
# import 作用:导入模块
# my_package.module1 作用:导入 my_package 包中的 module1 模块
result = my_package.module1.connect_database()
# my_package.module1.connect_database 作用:调用模块中的函数
# () 作用:调用函数
print(result) # 输出:数据库连接成功
为什么重要:
- 掌握导入语法:学会如何导入包中的模块
- 理解调用方式:掌握如何通过包路径调用模块中的函数
- 实践完整导入:理解从包到模块到函数调用的完整链路
逐行代码解释:
- import my_package.module1:导入整个 module1 模块
- my_package.module1.connect_database():调用 module1 中的 connect_database 函数
- print(result):打印结果
2. 使用 from...import 导入
# 🔥 重要!建议手写实现这段代码,理解 from...import 导入方式
from my_package import module1
# from 作用:从某个包导入
# my_package 作用:指定从 my_package 包导入
# import module1 作用:导入 module1 模块
result = module1.connect_database()
# module1.connect_database 作用:调用 module1 中的函数
print(result) # 输出:数据库连接成功
为什么重要:
- 掌握 from 导入:学会 from...import 语法
- 理解导入优势:掌握这种导入方式的简洁性
- 实践常用语法:这是 Python 中最常用的导入方式之一
逐行代码解释:
- from my_package import module1:从 my_package 包中导入 module1 模块
- module1.connect_database():调用 module1 中的函数
- print(result):打印结果
对比示例:
使用 from...import(推荐)
from my_package import module1
result = module1.connect_database() # 简洁明了
不使用 from...import(不推荐)
import my_package.module1
result = my_package.module1.connect_database() # 代码冗长
3. 导入特定函数
# 🔥 重要!建议手写实现这段代码,理解导入特定函数的方式
from my_package.module1 import connect_database
# from 作用:从某个包和模块导入
# my_package.module1 作用:指定从 my_package 包中的 module1 模块导入
# import connect_database 作用:导入 connect_database 函数
result = connect_database()
# connect_database 作用:直接调用函数
print(result) # 输出:数据库连接成功
为什么重要:
- 掌握精确导入:学会如何只导入需要的函数
- 理解导入优势:掌握导入特定函数的简洁性
- 实践最佳实践:这是 Python 推荐的导入方式
逐行代码解释:
- from my_package.module1 import connect_database:从包中导入特定的函数
- connect_database():直接调用函数,不需要写模块名
- print(result):打印结果
对比示例:
导入特定函数(推荐)
from my_package.module1 import connect_database
result = connect_database() # 最简洁
导入整个模块(不推荐)
import my_package.module1
result = my_package.module1.connect_database() # 需要写完整的路径
📖 深入学习:相对导入 vs 绝对导入
相对导入
生活化比喻:相对导入就像"我家隔壁的邻居"(用 . 表示当前位置)。
# 在 my_package/module1.py 中
from . import module2
# from . 作用:从当前包目录导入(. 表示当前目录)
# import module2 作用:导入同一包下的 module2 模块
from .module2 import read_file
# from .module2 作用:从当前包目录中的 module2 模块导入
# import read_file 作用:导入 read_file 函数
逐行代码解释:
- from . import module2:相对导入,从当前目录导入 module2
- . 作用:表示当前包目录
- from .module2 import read_file:从 module2 模块中导入 read_file 函数
优势:
- 代码简洁
- 便于移动和重命名包
- 避免硬编码包名
绝对导入
生活化比喻:绝对导入就像"完整的地址"(从根目录开始的完整路径)。
from my_package import module1
# from my_package 作用:从项目根目录的 my_package 包导入
# import module1 作用:导入 module1 模块
from my_package.module1 import connect_database
# from my_package.module1 作用:从 my_package 包中的 module1 模块导入
# import connect_database 作用:导入 connect_database 函数
逐行代码解释:
- from my_package import module1:绝对导入,从项目根目录的 my_package 包导入
- from my_package.module1 import connect_database:绝对导入,导入特定函数
优势:
- 清晰明确
- 不依赖当前位置
- 适合复杂的项目结构
对比表格
| 导入方式 | 语法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 相对导入 | from . import module | 简洁、易移动 | 依赖相对位置 | 包内部模块间 |
| 绝对导入 | from my_package import module | 清晰、不依赖位置 | 代码较长 | 跨包导入 |
📖 深入学习:实际应用场景进阶
场景 1:工具函数模块 🔥 重要!必须掌握
创建 calculator.py 模块:
# calculator.py
# 这是一个计算器模块
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
if y == 0:
return "除数不能为 0"
return x / y
使用模块:
# main.py
# 🔥 重要!建议手写实现这段代码,理解模块导入和使用的完整流程
import calculator
# import 作用:导入计算器模块
result1 = calculator.add(10, 5) # 15
result2 = calculator.subtract(10, 5) # 5
result3 = calculator.multiply(10, 5) # 50
result4 = calculator.divide(10, 5) # 2.0
print(result1, result2, result3, result4)
为什么重要:
- 理解模块导入:掌握如何导入和使用自定义模块
- 学会函数调用:理解如何调用模块中的函数
- 实践完整流程:从创建模块到导入使用的完整过程
适用水平:小白及以上
学习建议:掌握基本的模块创建和导入
场景 2:数据库操作包 ⭐ 建议掌握
包结构:
db_package/
├── __init__.py
├── database.py # 数据库连接
└── query.py # 查询操作
__init__.py 文件完整示例:
# db_package/__init__.py
# 🔥 重要!建议手写实现这段代码,理解 __init__.py 的完整用法
# 方法一:导入包中的模块(基本用法)
from . import database
from . import query
# 方法二:控制 from package import * 的行为(高级用法)
__all__ = ['database', 'query']
# __all__ 作用:定义包的公共接口(控制导入的内容)
# ['database', 'query'] 作用:指定通过 from db_package import * 时导入的模块
# 方法三:在包级别定义变量和函数(进阶用法)
PACKAGE_VERSION = "1.0.0"
# PACKAGE_VERSION 作用:定义包版本号,可以在其他地方使用
def get_version():
# def 作用:定义函数
# get_version 作用:获取包版本的函数
return PACKAGE_VERSION
# return 作用:返回版本号
# 方法四:执行包的初始化代码(高级用法)
print("db_package 包已加载")
# print 作用:在包被导入时打印提示信息
# 这会在 import db_package 时自动执行
逐行代码解释:
- from . import database:从当前包目录导入 database 模块
- from . import query:从当前包目录导入 query 模块
- all = ['database', 'query']:定义包的公共接口,控制
from db_package import *时只能导入 database 和 query - PACKAGE_VERSION = "1.0.0":定义包级别的变量,可以在其他地方通过
db_package.PACKAGE_VERSION访问 - def get_version():定义包级别的函数,可以在其他地方通过
db_package.get_version()调用 - print("db_package 包已加载"):在包被导入时执行一次,用于包的初始化
为什么重要:
- 理解 init.py 的基本用法:导入包中的模块
- 掌握 init.py 的高级用法:使用 all 控制包的导入行为、定义包级别变量和函数
- 学会包的初始化:理解如何在包加载时执行初始化代码
- 实践最佳实践:明确包的公共接口,隐藏内部实现
生活化解释:
- all:像门卫,控制谁能进入(哪些模块可以被导入)
- 包级别变量和函数:像仓库的公告栏和前台服务,提供统一的服务
- 初始化代码:包启动时会执行一次,像开门铃声提示
使用示例:
# main.py
import db_package
# 输出:db_package 包已加载(自动执行)
# 访问包级别的变量
print(db_package.PACKAGE_VERSION) # 输出:1.0.0
# 调用包级别的函数
print(db_package.get_version()) # 输出:1.0.0
# 使用包中的模块
from db_package import database
database.connect()
使用包:
# main.py
# ⭐ 建议手写实现这段代码,理解包的使用方式
import db_package
# import 作用:导入数据库操作包
# 使用包中的模块
db_package.database.connect()
result = db_package.query.select_all()
为什么重要:
- 理解包的结构:掌握 init.py 文件的作用
- 学会包的使用:理解如何导入和使用包中的模块
- 实践项目组织:学会如何组织大型项目的代码结构
适用水平:中级及以上
学习建议:掌握包的创建和使用
📖 深入学习:常见问题与解决方案
问题 1:ModuleNotFoundError(找不到模块)
错误信息:ModuleNotFoundError: No module named 'my_module'
❌ 错误做法
# 模块文件在项目外部,没有添加到搜索路径
import my_module # 报错:找不到模块
✅ 正确做法
import sys
sys.path.append('/path/to/module') # 添加模块路径
import my_module # 成功导入
解决方案:
- 将模块放在当前目录
- 使用
sys.path.append()添加路径 - 使用 PYTHONPATH 环境变量
问题 2:循环导入
错误场景:模块 A 导入模块 B,模块 B 又导入模块 A
❌ 错误做法
# module_a.py
import module_b # 导入模块 B
# module_b.py
import module_a # 导入模块 A(循环导入!)
✅ 正确做法
# module_a.py
def function_a():
# 按需导入,避免循环
from module_b import function_b
return function_b()
解决方案:
- 重新组织代码结构
- 使用局部导入(在函数内导入)
- 将公共代码提取到第三方模块
📚 深入学习:参考资料
相关学习资源
深入学习推荐
想详细了解的内容 → 推荐阅读的文档:
-
想深入了解 Python 模块导入机制
- 📚 阅读:Python 官方文档 - 模块
- 🔗 链接:docs.python.org/3/tutorial/…
- 💡 内容:模块搜索路径、导入机制、命名空间
-
想学习包的高级用法
- 📚 阅读:Python 官方文档 - 包
- 🔗 链接:docs.python.org/3/tutorial/…
- 💡 内容:包结构、init.py、相对导入、绝对导入
-
想了解命名空间包(Python 3.3+)
- 📚 阅读:PEP 420 官方文档
- 🔗 链接:www.python.org/dev/peps/pe…
- 💡 内容:命名空间包的原理、使用场景、最佳实践
-
想学习模块导入的最佳实践
- 📚 阅读:Python 模块导入机制与最佳实践
- 🔗 链接:www.cnblogs.com/bananaplan/…
- 💡 内容:15 个最佳实践、命名空间管理、性能优化
-
想掌握 import vs from import 的区别
- 📚 阅读:Python 模块导入的深层区别
- 👤 作者:掘金技术文章
- 🔗 链接:juejin.cn/post/749562…
- 💡 内容:命名空间、内存占用、可读性、性能分析
-
想学习 init.py 的高级用法
- 📚 阅读:掘金 - Python 模块与包详解
- 👤 作者:掘金技术文章
- 🔗 链接:juejin.cn/post/749562…
- 💡 内容:all、包初始化、接口设计、最佳实践
相关工具推荐
开发环境:
- Python 官方 IDE:IDLE
- 推荐编辑器:PyCharm、VS Code
- 在线练习:Python Tutor
学习资源:
- Python 模块教程 - 菜鸟教程:www.runoob.com/python/pyth…
- Python 包教程 - 廖雪峰教程:www.liaoxuefeng.com/wiki/101695…
模块搜索路径
Python 解释器查找模块的顺序:
- 当前目录:程序运行时的当前目录
- PYTHONPATH 环境变量:用户定义的搜索路径
- 标准库目录:Python 安装目录中的标准库
- site-packages 目录:第三方库安装目录
查看模块搜索路径:
import sys
# import 作用:导入 sys 模块
# sys 作用:Python 系统相关的模块
print(sys.path)
# sys.path 作用:模块搜索路径列表
# print 作用:打印搜索路径
🎉 总结与展望
Python 模块与包是代码组织的核心机制,通过模块(Module)文件化组织、包(Package)目录化管理、import 导入机制实现代码复用与结构化。掌握模块与包,可构建可维护、可扩展的项目。
🌟 核心价值回顾
- 代码复用:将常用功能封装成模块,避免重复编写
- 结构化组织:使用包管理相关模块,保持项目清晰
- 团队协作:模块化开发便于多人协作和版本控制
- 易于维护:代码分离,问题定位更快速
💪 学习建议
- 从简单开始:先掌握 import 导入内置模块
- 多实践:创建自己的模块和包
- 循序渐进:从单个模块到包结构
- 关注规范:遵循 Python 的命名和导入规范
继续实践,代码组织能力将不断提升!
厦门工学院人工智能创作坊 -- 郑恩赐
2025 年 10 月 28 日