Python 项目目录结构应该怎么设计?src layout 有什么好处?
简化版
Python 项目常见结构有 flat layout 和 src layout。src layout 把包代码放到 src/<package>/,测试放到 tests/,能避免测试时误导入项目根目录下的源码,帮助发现打包配置问题,更适合可发布包和中大型项目。
详细版
典型结构:
project/
pyproject.toml
src/
myapp/
__init__.py
service.py
tests/
test_service.py
flat layout 简单,适合小脚本;src layout 更严格,测试更接近安装后的使用方式。面试重点是:目录结构要服务导入清晰、测试隔离、打包发布和团队协作。
完整版教学
一、为什么目录结构影响质量
Python 的导入路径和当前工作目录关系很大。结构混乱时,测试可能导入了本地源码,却没有验证包是否能正确安装。上线后才发现包数据、入口或依赖缺失。
测试能 import,不代表安装后能 import
目录结构就是把导入边界固定下来。
二、flat layout 是什么
flat layout 把包直接放项目根目录:
project/
myapp/
tests/
pyproject.toml
它短小直观,适合简单应用。但项目根目录在测试时常进入 sys.path,容易掩盖打包配置错误。
三、src layout 是什么
src layout 把代码放入 src/:
project/
src/myapp/
tests/
测试如果要导入 myapp,通常需要以 editable install 或正确配置路径方式安装。这能更早发现“包没有被正确声明”的问题。
src layout 的价值是让测试更接近真实安装后的导入方式。
四、tests 应该怎么组织
测试目录可以按模块镜像组织,也可以按功能组织。关键是命名清晰、fixture 复用合理、不要让测试依赖执行顺序。
tests/
unit/
integration/
conftest.py
conftest.py 放 pytest fixture,但不要塞太多隐式魔法,否则测试可读性下降。
五、配置文件放哪里
现代项目把构建、依赖、工具配置尽量放 pyproject.toml。README、LICENSE、Dockerfile、CI 配置放根目录,运行时配置不要和代码配置混淆。
pyproject.toml -> 构建/依赖/工具
.env.example -> 环境变量示例
秘密值不要提交。
六、应用项目和库项目不同
库项目更关注发布、版本、公共 API;应用项目更关注配置、部署、迁移脚本、运行入口。结构要根据目标调整。
| 类型 | 关注点 |
|---|---|
| 库 | 打包、API、兼容性 |
| Web 应用 | 配置、入口、迁移、部署 |
| 脚本工具 | CLI、配置、日志 |
不要盲目套模板。
七、常见误区与追问
- 误区:目录怎么放都不影响运行。 导入路径、测试和打包都会受影响。
- 误区:src layout 只是多一层目录。 它能暴露打包和导入问题。
- 误区:tests 应该放包里面。 多数项目放根 tests 更清晰,库也可按需放包内。
- 追问:editable install 是什么? 让环境以可编辑方式安装本地包,测试导入安装后的包名。
- 追问:conftest 放什么? 共享 fixture 和 pytest 钩子。
- 追问:脚本入口放哪里? 小项目可 scripts,包内 CLI 用 project.scripts。
- 追问:配置文件要提交吗? 示例提交,秘密不提交。
八、加强记忆
项目结构记成“导入清楚、测试真实、打包可靠”。小项目 flat 可以,中大型和可发布包更推荐 src layout。结构不是审美问题,而是让测试和部署更接近真实环境。