人人都会AI编程

23.1 项目目录结构规范:分层设计、模块划分

更新时间:2026-07-12

一个 Python 项目从“能跑”到“好维护”,往往就差在一个清晰合理的目录结构上。好的项目结构不是教条式的模板,而是让代码组织符合逻辑不同职责的代码各居其位,从而让新成员快速上手、让旧功能改动时不致牵一发动全身。

分层设计:把项目拆成职能清晰的几层

绝大多数 Python 应用的共同点是:它们都有数据存取业务逻辑对外接口这三个层面的职责。分层设计就是把它们分开,让上层依赖下层,下层不感知上层。常见的分层方式如下:

  • 表现层(Presentation)

负责接收外部请求、校验输入、构造输出、返回响应。如果是 Web 项目,这里放路由处理函数视图序列化器等。

  • 业务逻辑层(Service / Domain)

这是项目的核心,负责具体业务的规则处理、数据计算、流程编排。这一层不依赖特定框架,尽量保持纯 Python 逻辑,便于单元测试。

  • 数据访问层(Repository / DAO)

负责和数据库、外部 API、文件系统打交道。通常会把 SQL 查询、ORM 操作、第三方 SDK 调用都封装在这一层。

  • 基础设施层(Infrastructure)

提供与业务无关的基础支撑,例如配置加载、日志记录、连接池、消息队列客户端等。它通常被其他各层共同使用。

实际项目中不必机械地追求四层拆分,小的脚本可能只需两层(接口 + 数据),中型应用常用“Router → Service → Repository”三层。核心原则是:不让业务逻辑散落在控制器或 SQL 语句里。

模块划分:让每个文件只做一件事

目录结构就是分层在文件系统上的投影。一个可维护的 Python 项目目录通常长这样(以 Web 应用为例):

project/
├── src/                     # 主应用代码
│   ├── api/                 # 表现层:路由、视图、请求处理
│   │   ├── v1/
│   │   │   ├── users.py     # 用户相关接口
│   │   │   └── orders.py
│   │   └── deps.py          # 公用依赖(认证、参数校验)
│   ├── services/            # 业务逻辑层
│   │   ├── user_service.py
│   │   └── order_service.py
│   ├── repositories/        # 数据访问层
│   │   ├── user_repo.py
│   │   └── order_repo.py
│   ├── models/              # ORM 模型 / DTO 实体
│   │   ├── user.py
│   │   └── order.py
│   ├── schemas/             # 输入输出序列化校验(如 Pydantic models)
│   └── core/                # 基础设施:配置、日志、数据库连接
│       ├── config.py
│       └── database.py
├── tests/                   # 测试目录,镜像 src 结构
│   ├── api/
│   ├── services/
│   └── conftest.py
├── scripts/                 # 一次性脚本、数据迁移脚本
├── pyproject.toml           # 项目元数据与依赖
├── Dockerfile
└── README.md

为什么要这样划分?

  1. 职责清晰,修改定位快

订单业务变更时,你直奔 services/order_service.py 修改逻辑即可;数据库表结构变了,只需调整 models/repositories/,不影响其他部分。

  1. 易于复用与测试

业务逻辑层是纯 Python 对象,可以被任何接口(HTTP、命令行、定时任务)调用;测试时快速构造输入、mock 掉数据层依赖,单元测试可以写得很细腻。

  1. 避免循环导入

分层后,依赖方向是单向的:apiservicesrepositoriesmodels。只要遵守这个方向,就不会出现模块 A 导入模块 B、模块 B 又导入模块 A 的死锁。

  1. 团队协作不撞车

多人开发时,按模块分工不容易冲突。前端工程师关注 api/,后端逻辑在 services/,数据库相关在 models/repositories/

几个容易踩的坑

  • 别一开始就过度设计

如果只是一个几十行的数据处理脚本,不需要强套分层,一个文件解决问题更务实。

  • 不要按文件类型分,要按业务模块分

“把所有的路由放一起、所有的模型放一起”只适合微型项目。项目稍大就应按业务领域拆分,否则一个文件上千行,根本没法维护。

  • 保持导入路径清晰

尽量使用绝对导入,少用相对导入,配置好 pyproject.toml 和包结构,让 from src.services.user_service import UserService 始终可寻址。

实践建议

  • 项目早期就选择一个主流的结构模板并坚持用下去。FastAPI 推荐的结构、Django 自带的 app 结构、或者经典 Clean Architecture 的 Python 实现,都是不错的起点。
  • 合理使用 init.py 将子目录组织为包,并在其中暴露对外的 API,可以简化调用方的导入路径。
  • 搭配类型提示和 linter(mypy、ruff)在大型项目中强制约束模块边界,防止低层次代码偷偷直接调用高层次符号。

最终,一个好的目录结构不是刻板的教条,而是可以让团队形成共同认知的物理地图,让代码的导航和维护成本降到最低。