Python包结构设计教程_大型项目代码组织方式

大型Python项目应按业务域分层,如orders/、products/,每域内设domain/application/infrastructure子包;公共能力抽为shared/;接入层(api/cli)仅作输入输出,业务逻辑全在application层;测试与代码同目录;__init__.py显式声明公共API。

大型Python项目不是把所有代码塞进一个文件夹就完事,关键在于分层清晰、职责明确、易于测试和扩展。包结构设计本质是定义模块间的依赖边界和演进路径。

核心原则:按领域分层,而非技术类型

别用“models/”、“views/”、“utils/”这种纯技术分类方式堆砌目录——它会让业务逻辑四处散落,改一个功能要跳转七八个地方。应该以业务域(Domain)或核心能力为单位组织顶层包。

  • 例如电商项目,顶层可设 orders/products/payments/,每个包内再按需包含 domain/(实体、值对象、领域服务)、application/(用例、DTO、命令处理)、infrastructure/(数据库适配、第三方API封装)
  • 公共基础能力(如日志、配置、异常体系)单独抽成 shared/common/ 包,禁止业务包直接 import 其他业务包的内部模块
  • 顶层不放 .py 文件,只保留 __init__.py(可为空)和 pyproject.toml 相关配置

入口与隔离:main 和 api 层要轻量且无业务逻辑

CLI 命令、Web 接口、定时任务等都属于“接入层”,只负责解析输入、调用 application 层、格式化输出。它们不能持有领域模型,也不能直连数据库。

  • cli/ 下每个命令对应一个独立模块,如 cli/order_create.py,仅初始化命令参数并转发给 orders.application.create_order()
  • api/(如 FastAPI)中路由函数只做数据校验和 DTO 转换,业务动作全部委托给 application 层函数或类方法
  • 接入层通过依赖注入容器(如 dependencies.py)获取 service 实例,避免硬编码初始化

测试友好性:每个业务包自带 tests/ 子目录

测试代码必须和被测代码物理相邻,而不是全堆在项目根目录的 tests/ 里。这样重构某个域时,能一眼看到影响范围,并快速运行对应测试。

立即学习“Python免费学习笔记(深入)”;

  • 每个 orders/ 包下建 tests/,结构镜像源码:tests/domain/test_order.pytests/application/test_create_order.py
  • 单元测试聚焦单个函数或类,用 unittest.mockpytest-mock 替换 infrastructure 依赖(如 mock 数据库 session)
  • 集成测试放在项目级 tests/integration/,验证跨包协作,例如“下单 → 扣库存 → 发通知”全流程

可维护细节:__init__.py 的公开接口控制

每个包的 __init__.py 是该包对外的“门面”。它不该是自动导入所有子模块的中转站,而应显式声明哪些符号是供外部使用的稳定 API。

  • orders/__init__.py 可写:# public API
    from .application import create_order, cancel_order
    from .domain import Order, OrderStatus
  • 隐藏实现细节:不导出 infrastructure/ 下的类,不导出 domain/_validation.py 这类私有模块
  • 配合 py.typed 文件 + 类型注解,让 mypy 和 IDE 精准识别包的公共契约