摘要:在 Python 编程中,项目、包、模块与库/分发件是构建与组织代码的基石。理解它们的边界与联系,有助于合理规划目录结构、提升可维护性与复用性。
在 Python 编程中,项目、包、模块与库/分发件是构建与组织代码的基石。理解它们的边界与联系,有助于合理规划目录结构、提升可维护性与复用性。
一、项目
项目(Project)是一个完整的软件工程集合,既包含源代码,也包含构建、测试、文档与配置等配套内容。
1、常见组成
一个或多个包/模块(源码)
构建与依赖:pyproject.toml(或早期的 setup.cfg/setup.py)
环境锁定:requirements.txt(部署环境用)
测试代码:tests/
文档与说明:README.md、LICENSE
版本控制信息:.git/
2、推荐目录结构(src 布局)
my_project/ ← 项目根目录│├── pyproject.toml ← 构建元数据与依赖(推荐)├── requirements.txt ← 部署/环境锁定(可选)├── README.md ← 项目说明├── LICENSE ← 许可证│├── src/ ← 源代码根目录(库项目推荐使用)│ └── my_package/ ← 顶层包(regular 或 namespace)│ ├── __init__.py ← 常规包需要;命名空间包不需要│ ├── module_a.py│ └── module_b.py│└── tests/ ← 测试代码(pytest 等)提示:
应用型项目可使用平铺布局。
库项目推荐使用 src 布局,以避免“测试能导入,但安装后失败”的问题。
二、包
包(Package)用于分层组织模块,支持点号分隔的层级命名,如:
my_package.subpkg.module_x1、分类
(1)常规包(regular package)
目录中包含 __init__.py(可为空)。
导入时会创建包对象并执行 __init__.py 中的初始化代码。
可在 __init__.py 中定义 __all__ 来控制 from pkg import * 的导出。
(2)命名空间包(namespace package,Python 3.3+)
目录中不包含 __init__.py。
允许将同名顶层包拆分到多个目录/分发件中,例如多个 wheel 共同提供 my_package 的不同子包。
没有 __init__.py,因此不能在导入时执行初始化逻辑;一些属性如 __file__ 不可用。
导入示例:
# src/my_package/module_a.pydef add(x, y):return x + y# 另一个模块import my_package.module_afrom my_package.module_a import addprint(add(2, 3)) # 输出 5提示:
对外 API 推荐使用绝对导入。
包内部可用相对导入,如:
from .module_a import add from ..subpkg import util三、模块
模块(Module)是 Python 程序组织与导入的基本单元,不仅仅是 .py 文件。
1、模块类型
纯 Python 源文件:xxx.py
编译扩展模块:xxx.pyd(Windows)/xxx.so(Linux/macOS)
内建模块:由解释器内置(如 sys)
包的子模块(包目录+子文件)
2、特点
文件名即模块名(不含后缀)
模块提供独立命名空间,便于复用与维护
模块不仅能导入,还能直接运行。
3、模块与脚本
在 Python 中,脚本(script)不是独立概念,而是模块的一种使用方式。
作为模块:通过 import 使用
from my_package import module_amodule_a.some_function作为脚本:
# 直接运行文件python module_a.py# 或通过 -m 参数运行模块python -m my_package.module_a惯例写法:
提示:
当文件以脚本运行时,__name__ == "__main__"。
当文件作为模块导入时,__name__ 等于模块名。
四、库 / 分发件
分发件(distribution)指的是面向发布/安装的产物(wheel/sdist)。在日常口语中常被称作 “库”(library),但在严格语境下,库是功能集合,而分发件是发布形态。
1、类型
标准库:随解释器一起发布(如 os、sys、math)。
第三方库:发布在 PyPI 或私有仓库(如 requests、numpy、pandas)。
形态上可以是:
单模块库(一个 .py)
单包库(一个包目录)
多包/多模块的组合
2、分发与安装关键点
(1)分发格式
wheel(.whl):已构建好的二进制/纯 Python 分发件,安装快。
sdist(源分发):源码压缩包,安装时本地构建。
(2)依赖声明
在 pyproject.toml([project] dependencies = [...])中声明运行依赖;
测试/开发依赖可写在工具配置段(如 tool.poetry、tool.uv),或额外维护 requirements-dev.txt。
(3)环境锁定
requirements.txt 更适用于部署环境(可固定版本号),不建议用它作为分发元数据的来源。
3、要点对比
包:导入层面的对象(目录+__init__.py 或命名空间包)。
库/分发件:发布与安装层面的对象(wheel/sdist)。
一个库通常作为分发件发布,内部可能包含一个或多个包/模块。
五、补充说明
1、项目 vs 库
项目面向运行,库面向复用。一个项目也可同时提供命令行入口和 API。
2、包 vs 普通目录
常规包有 __init__.py;命名空间包无 __init__.py;普通目录不可导入。
3、模块 vs 脚本
模块可导入;脚本是运行方式,本质仍是模块。
4、库 vs 框架
框架(如 Django)约束更强,通常控制应用结构;库仅提供功能调用。
5、导入路径
解释器按 sys.path 搜索,安装的包位于 site-packages。
六、命名空间包示例(进阶)
目录 A(分发件 A):
src/└── myns/ ← 无 __init__.py└── alpha/└── a.py目录 B(分发件 B):
src/└── myns/ ← 无 __init__.py└── beta/└── b.py安装两者后,导入路径统一聚合为同一个顶层包 myns:
from myns.alpha import afrom myns.beta import b注意:若放入 __init__.py 就不再是命名空间包,无法跨分发件聚合;并且命名空间包不支持在导入时执行初始化逻辑。
七、实践建议
1、做库
采用 src 布局,pyproject.toml 声明依赖,用 wheel 分发。
2、做应用
可平铺或 src 布局;入口可用 __main__.py 或 console_scripts。
3、包选择
除非需要多仓库聚合,否则使用常规包。
4、导入风格
对外 API 用绝对导入;包内可用相对导入。
5、测试
源码与 tests/ 并列,确保通过“已安装”方式导入。
小结
模块(module):既可导入也可直接执行的代码单元(.py 文件、内建模块、扩展模块等)。
包(package):包含层级命名的模块容器(常规包或命名空间包)。
项目(project):包含代码、配置、测试、文档等内容的完整工程集合。
分发件(distribution):面向发布与安装的产物(wheel/sdist)。日常口语常称“库”,严格来说库是功能集合,而分发件是其发布形态。
“点赞有美意,赞赏是鼓励”
来源:豆豆妈