目录结构从来不是“放文件的细节”,而是项目认知的一部分。一个结构清晰的 Python 项目,会天然帮助你划清模块边界、减少循环依赖、提高新成员的理解速度。
这一节我们会分别讨论脚本型项目、库项目和服务项目的组织思路,看看配置、入口、常量、公共工具和业务模块到底应该如何拆分,才能让结构真正服务于维护。
从单文件脚本到多目录项目
很多 Python 项目最早都是从一个文件开始的,这没有问题。问题出在业务长大以后,还是把所有东西都堆在一个入口文件里。
一旦代码里同时混着:
- 配置读取;
- 参数解析;
- 核心业务逻辑;
- 网络请求;
- 文件写入;
- 日志打印;
整个文件就会迅速变成难以维护的泥团。
所以项目结构的核心目的,不是追求“目录很多”,而是帮助你尽早把不同职责拆开。
脚本型项目的结构建议
脚本型项目通常关注的是“完成一个任务”,比如批量处理文件、拉取数据、生成报表。
这类项目即使不大,也建议至少区分:
- 入口脚本;
- 核心处理逻辑;
- 配置读取;
- 公共工具。
因为一旦脚本需要重复运行、加入参数、增加测试,结构清晰与否的差别就会立刻体现出来。
所以即便是“只是个脚本”,只要它不是一次性就丢的代码,也值得有最基础的模块边界。
库项目与服务项目的结构差异
库项目和服务项目虽然都可能是 Python 包,但组织重点不同。
库项目更关心:
- 对外暴露什么 API;
- 内部模块如何拆分;
- 安装后别人怎么引用。
服务项目则更关心:
- 请求入口和路由;
- 业务层;
- 数据访问层;
- 配置和生命周期管理。
所以结构不是一套模板走天下,而是要跟项目类型匹配。判断标准不是“别人都这么放”,而是“这个结构能不能把当前项目的职责表达清楚”。
配置、常量与公共工具如何放置?
这几类东西最容易被随手乱塞。
一个很常见的坏味道是:
- 配置直接散在业务模块里;
- 常量在多个文件重复出现;
utils.py变成巨型杂物间。
更合理的做法通常是:
- 配置集中管理,并明确区分运行环境;
- 常量按业务域归类,而不是全项目扔进一个
constants.py; - 公共工具只保留真正跨模块复用、且语义稳定的能力。
换句话说,公共模块不是“放不下的都丢过去”,而应该是项目里最克制、最有边界感的区域之一。
入口文件、模块边界与依赖方向
一个结构清晰的项目,通常能回答这三个问题:
- 程序从哪里启动?
- 核心业务逻辑放在哪里?
- 依赖方向是否稳定?
尤其要注意依赖方向。入口层可以依赖业务层,业务层可以依赖基础设施层,但反过来就容易把结构缠死。
一旦底层工具模块开始依赖路由层、CLI 层或视图层,项目很快就会出现循环依赖和职责混乱。
所以结构设计最重要的不是“画个好看的树”,而是让依赖方向尽量单向、稳定、可理解。
一个好结构应该具备什么特征?
好的项目结构通常不一定复杂,但会具备这些特征:
- 新成员能快速找到入口;
- 模块职责能一句话说清;
- 公共能力集中而克制;
- 依赖方向稳定,不容易互相缠绕;
- 后续增加测试、配置、构建时不需要推翻重来。
你会发现,结构设计的本质其实和函数设计、类设计很像,都是在做边界管理。
总结与预告
这一节我们从脚本、包到服务三个层面理解了结构设计的差异。结构从来不是审美问题,而是复杂度管理问题,好的结构会让职责更清楚,让协作和演进都轻松很多。
下一节我们会继续围绕复用能力展开,把本地代码真正推进到可安装、可发布、可被其他项目消费的 Python 包。