【Python】项目结构
- 前言
- 前置知识
- Python 的基本项目结构
- `int main()` 与 `def main()` 的区别
- 举例:基于 KNN 的 OpenCV 数字识别的项目结构
前言
本文总结了 Python 项目结构的知识,规范项目结构能使得项目开发过程高效流畅,提升代码可读性、团队协作效率,并便于维护、扩展和共享。
参考文章:
各类 Python 项目的项目结构及代码组织最佳实践
前置知识
什么是 Package(包)
包(Package)是一个文件夹,用于存放相关模块、子包、说明文档和配置文件,通常与项目的工程文件夹相对应。包能够将相关模块按功能组织,避免文件混乱。如果你有 STM32 等项目经验,这会更易理解。
ps:
包目录中必须包含 __init__.py
文件,以表明该文件夹是包。若缺少 __init__.py
,Python 将无法识别该文件夹为包,导入时会报错。
Package包与 Directories目录的区别:虽然在外观上,Package 和普通目录类似,但包目录中必须包含 __init__.py
文件,而普通目录没有这个要求。包是为了组织 Python 代码模块而存在的,是 Python 中代码管理和复用的方式。
什么是 Module(模块)
模块(Module)是 Python 中的代码文件,一般是 .py
后缀的文件,用于存放可以复用的函数、类或变量等代码。模块使代码更易管理和复用。每个 .py
文件都可以看作是一个独立的模块,可以通过 import
语句在其他代码中使用。
Package 包与 Module 模块的关系
Package 包可以包含多个 Module 模块。包是模块的集合,它通过将多个相关的模块组合在一起,形成一个结构化的代码体系,从而方便代码的组织、分发和复用。
__init__.py
详解
__init__.py
文件的作用是让 Python 识别某个目录为包,同时可以在其中定义一些包的初始化逻辑,例如导入子模块等。如果 __init__.py
为空,表示这是一个基础的包,包含了默认的模块结构。自 Python 3.3 之后,即使没有 __init__.py
,Python 也能识别包,但为了兼容性和代码规范,通常还是建议保留该文件。
Python 的基本项目结构
假设项目名称为 myproject
,一个标准的项目结构如下:
myproject/ # 根目录
│ .gitignore
│ LICENSE
│ readme.md
│ requirements.txt
│ setup.py
│
├─myproject/ # 包目录 (项目核心模块代码)
│ main.py # 主函数,程序的入口
│ module1.py # 模块1代码
│ module2.py # 模块2代码
│ __init__.py # 初始化文件
│
└─test/ # 测试目录test_main.py # 测试 main.py 中的功能
项目根目录说明
.gitignore
:用于记录不希望提交到版本控制系统(如 Git)的文件,例如虚拟环境、编译生成的文件、日志等。(Git是一个帮助多人协作开发和管理代码的工具,它可以记录每次修改)LICENSE
:项目的许可说明文件,定义代码的使用权限。如果是个人或比赛项目,可以省略。readme.md
:项目的说明文档,提供项目的基本信息、功能介绍、安装方法、使用说明等。通常是项目的第一份文档,便于其他人快速了解项目。requirements.txt
:列出项目所需的第三方依赖库及其版本,便于其他人通过pip install -r requirements.txt
快速配置项目环境。setup.py
:一键配置项目环境的打包配置文件,定义项目的基本信息(如名称、版本、作者、依赖库等),以及指定如何将代码打包成可安装的形式。
对于比赛或小项目,项目结构可以简化,.gitignore、LICENSE、requirements.txt和 setup.py可适当忽略
包目录说明
- 包目录 (
myproject/
)main.py
:通常是项目的主入口,用于实现项目的逻辑。modulex.py
:模块代码,用于实现模块的基本功能__init__.py
:初始化操作(如 import)
测试目录说明
- 测试目录 (
test/
)test_main.py
:测试代码,通常以test_
开头,用于对项目中的模块和函数进行单元测试,确保项目的稳定性和正确性。
int main()
与 def main()
的区别
在 C 语言中,int main()
是程序的入口。而在 Python 中,没有固定的入口函数,但通常 main.py 被作为程序的入口文件。在 PyCharm 中,新建工程时默认会创建一个 main.py 文件(PyCharm的期望入口),你可以在其中 import 其他模块并调用它们的功能。
此外,也可以在 main.py 中 def 一个 main() 函数,并通过以下方式确保该函数只有在直接运行时才会执行:
if __name__ == "__main__":main()
这种写法确保了当 Python 文件被直接执行时调用 main(),但如果文件作为模块导入时,主函数不会自动执行。
举例:基于 KNN 的 OpenCV 数字识别的项目结构
knn_digit_recognition/
├── data/ # 数据集目录
│ ├── train_images/ # 训练集图片
│ ├── train_labels.csv # 训练标签(如 CSV 文件,存储图片与标签的对应关系)
│ ├── test_images/ # 测试集图片
│ └── test_labels.csv # 测试标签
│
├── src/ # 源代码目录(包目录)
│ ├── __init__.py # 标识 src 为包,初始化代码
│ ├── preprocess.py # 图像预处理代码(灰度、阈值、缩放等)
│ ├── knn_model.py # KNN 模型代码,包括训练和预测
│ ├── utils.py # 辅助函数(如数据加载、文件管理等)
│ └── main.py # 主程序,项目入口
│
├── tests/ # 测试代码
│ ├── test_preprocess.py # 测试预处理模块
│ ├── test_knn_model.py # 测试 KNN 模型
│ └── test_main.py # 测试主程序流程
│
├── .gitignore # Git 忽略文件
├── requirements.txt # 项目依赖项
├── README.md # 项目说明文档
└── setup.py # 安装和配置脚本