返回专题首页

Python 专题

如何组织一个 Python 项目:脚本、包与服务的结构设计

目录结构从来不是“放文件的细节”,而是项目认知的一部分。一个结构清晰的 Python 项目,会天然帮助你划清模块边界、减少循环依赖、提高新成员的理解速度。

Python 专题第 25 篇 / 39 篇4 分钟

目录结构从来不是“放文件的细节”,而是项目认知的一部分。一个结构清晰的 Python 项目,会天然帮助你划清模块边界、减少循环依赖、提高新成员的理解速度。

这一节我们会分别讨论脚本型项目、库项目和服务项目的组织思路,看看配置、入口、常量、公共工具和业务模块到底应该如何拆分,才能让结构真正服务于维护。

从单文件脚本到多目录项目

很多 Python 项目最早都是从一个文件开始的,这没有问题。问题出在业务长大以后,还是把所有东西都堆在一个入口文件里。

一旦代码里同时混着:

  • 配置读取;
  • 参数解析;
  • 核心业务逻辑;
  • 网络请求;
  • 文件写入;
  • 日志打印;

整个文件就会迅速变成难以维护的泥团。

所以项目结构的核心目的,不是追求“目录很多”,而是帮助你尽早把不同职责拆开。

脚本型项目的结构建议

脚本型项目通常关注的是“完成一个任务”,比如批量处理文件、拉取数据、生成报表。

这类项目即使不大,也建议至少区分:

  • 入口脚本;
  • 核心处理逻辑;
  • 配置读取;
  • 公共工具。

因为一旦脚本需要重复运行、加入参数、增加测试,结构清晰与否的差别就会立刻体现出来。

所以即便是“只是个脚本”,只要它不是一次性就丢的代码,也值得有最基础的模块边界。

库项目与服务项目的结构差异

库项目和服务项目虽然都可能是 Python 包,但组织重点不同。

库项目更关心:

  • 对外暴露什么 API;
  • 内部模块如何拆分;
  • 安装后别人怎么引用。

服务项目则更关心:

  • 请求入口和路由;
  • 业务层;
  • 数据访问层;
  • 配置和生命周期管理。

所以结构不是一套模板走天下,而是要跟项目类型匹配。判断标准不是“别人都这么放”,而是“这个结构能不能把当前项目的职责表达清楚”。

配置、常量与公共工具如何放置?

这几类东西最容易被随手乱塞。

一个很常见的坏味道是:

  • 配置直接散在业务模块里;
  • 常量在多个文件重复出现;
  • utils.py 变成巨型杂物间。

更合理的做法通常是:

  • 配置集中管理,并明确区分运行环境;
  • 常量按业务域归类,而不是全项目扔进一个 constants.py
  • 公共工具只保留真正跨模块复用、且语义稳定的能力。

换句话说,公共模块不是“放不下的都丢过去”,而应该是项目里最克制、最有边界感的区域之一。

入口文件、模块边界与依赖方向

一个结构清晰的项目,通常能回答这三个问题:

  • 程序从哪里启动?
  • 核心业务逻辑放在哪里?
  • 依赖方向是否稳定?

尤其要注意依赖方向。入口层可以依赖业务层,业务层可以依赖基础设施层,但反过来就容易把结构缠死。

一旦底层工具模块开始依赖路由层、CLI 层或视图层,项目很快就会出现循环依赖和职责混乱。

所以结构设计最重要的不是“画个好看的树”,而是让依赖方向尽量单向、稳定、可理解。

一个好结构应该具备什么特征?

好的项目结构通常不一定复杂,但会具备这些特征:

  • 新成员能快速找到入口;
  • 模块职责能一句话说清;
  • 公共能力集中而克制;
  • 依赖方向稳定,不容易互相缠绕;
  • 后续增加测试、配置、构建时不需要推翻重来。

你会发现,结构设计的本质其实和函数设计、类设计很像,都是在做边界管理。

总结与预告

这一节我们从脚本、包到服务三个层面理解了结构设计的差异。结构从来不是审美问题,而是复杂度管理问题,好的结构会让职责更清楚,让协作和演进都轻松很多。

下一节我们会继续围绕复用能力展开,把本地代码真正推进到可安装、可发布、可被其他项目消费的 Python 包。