python-project-structure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Python Project Structure & Module Architecture

Python项目结构与模块架构

Design well-organized Python projects with clear module boundaries, explicit public interfaces, and maintainable directory structures. Good organization makes code discoverable and changes predictable.
设计组织良好的Python项目,具备清晰的模块边界、明确的公共接口和可维护的目录结构。良好的项目组织能让代码更易查找,变更更可预测。

When to Use This Skill

何时使用该方法

  • Starting a new Python project from scratch
  • Reorganizing an existing codebase for clarity
  • Defining module public APIs with
    __all__
  • Deciding between flat and nested directory structures
  • Determining test file placement strategies
  • Creating reusable library packages
  • 从零开始新建Python项目
  • 重构现有代码库以提升清晰度
  • 使用
    __all__
    定义模块公共API
  • 选择扁平化或嵌套式目录结构
  • 确定测试文件的放置策略
  • 创建可复用的库包

Core Concepts

核心概念

1. Module Cohesion

1. 模块内聚性

Group related code that changes together. A module should have a single, clear purpose.
将相关且会同步变更的代码归为一组。每个模块应具备单一、明确的用途。

2. Explicit Interfaces

2. 明确的接口

Define what's public with
__all__
. Everything not listed is an internal implementation detail.
使用
__all__
定义公共内容。未列出的所有内容均为内部实现细节。

3. Flat Hierarchies

3. 扁平化层级

Prefer shallow directory structures. Add depth only for genuine sub-domains.
优先采用浅层次目录结构。仅当存在真正的子领域时才增加层级深度。

4. Consistent Conventions

4. 一致的约定

Apply naming and organization patterns uniformly across the project.
在项目中统一应用命名和组织模式。

Quick Start

快速开始

myproject/
├── src/
│   └── myproject/
│       ├── __init__.py
│       ├── services/
│       ├── models/
│       └── api/
├── tests/
├── pyproject.toml
└── README.md
myproject/
├── src/
│   └── myproject/
│       ├── __init__.py
│       ├── services/
│       ├── models/
│       └── api/
├── tests/
├── pyproject.toml
└── README.md

Fundamental Patterns

基础模式

Pattern 1: One Concept Per File

模式1:每个文件对应一个概念

Each file should focus on a single concept or closely related set of functions. Consider splitting when a file:
  • Handles multiple unrelated responsibilities
  • Grows beyond 300-500 lines (varies by complexity)
  • Contains classes that change for different reasons
python
undefined
每个文件应聚焦于单个概念或一组紧密相关的函数。当文件出现以下情况时,考虑拆分:
  • 处理多个不相关的职责
  • 代码行数超过300-500行(根据复杂度有所不同)
  • 包含因不同原因而变更的类
python
undefined

Good: Focused files

良好示例:聚焦单一的文件

user_service.py - User business logic

user_service.py - 用户业务逻辑

user_repository.py - User data access

user_repository.py - 用户数据访问

user_models.py - User data structures

user_models.py - 用户数据结构

Avoid: Kitchen sink files

避免:全能型文件

user.py - Contains service, repository, models, utilities...

user.py - 包含服务、数据访问、模型、工具等...

undefined
undefined

Pattern 2: Explicit Public APIs with
__all__

模式2:使用
__all__
定义明确的公共API

Define the public interface for every module. Unlisted members are internal implementation details.
python
undefined
为每个模块定义公共接口。未列出的成员均为内部实现细节。
python
undefined

mypackage/services/init.py

mypackage/services/init.py

from .user_service import UserService from .order_service import OrderService from .exceptions import ServiceError, ValidationError
all = [ "UserService", "OrderService", "ServiceError", "ValidationError", ]
from .user_service import UserService from .order_service import OrderService from .exceptions import ServiceError, ValidationError
all = [ "UserService", "OrderService", "ServiceError", "ValidationError", ]

Internal helpers remain private by omission

内部工具默认保持私有

from .internal_helpers import _validate_input # Not exported

from .internal_helpers import _validate_input # 未导出

undefined
undefined

Pattern 3: Flat Directory Structure

模式3:扁平化目录结构

Prefer minimal nesting. Deep hierarchies make imports verbose and navigation difficult.
undefined
优先采用最少嵌套的结构。过深的层级会导致导入语句冗长,且难以导航。
undefined

Preferred: Flat structure

推荐:扁平化结构

project/ ├── api/ │ ├── routes.py │ └── middleware.py ├── services/ │ ├── user_service.py │ └── order_service.py ├── models/ │ ├── user.py │ └── order.py └── utils/ └── validation.py
project/ ├── api/ │ ├── routes.py │ └── middleware.py ├── services/ │ ├── user_service.py │ └── order_service.py ├── models/ │ ├── user.py │ └── order.py └── utils/ └── validation.py

Avoid: Deep nesting

避免:过深的嵌套

project/core/internal/services/impl/user/

Add sub-packages only when there's a genuine sub-domain requiring isolation.
project/core/internal/services/impl/user/

仅当存在需要隔离的真正子领域时,才添加子包。

Pattern 4: Test File Organization

模式4:测试文件组织

Choose one approach and apply it consistently throughout the project.
Option A: Colocated Tests
src/
├── user_service.py
├── test_user_service.py
├── order_service.py
└── test_order_service.py
Benefits: Tests live next to the code they verify. Easy to see coverage gaps.
Option B: Parallel Test Directory
src/
├── services/
│   ├── user_service.py
│   └── order_service.py
tests/
├── services/
│   ├── test_user_service.py
│   └── test_order_service.py
Benefits: Clean separation between production and test code. Standard for larger projects.
选择一种方式并在整个项目中一致应用。
选项A:测试文件与代码同目录
src/
├── user_service.py
├── test_user_service.py
├── order_service.py
└── test_order_service.py
优势:测试文件紧邻其验证的代码。易于发现覆盖缺口。
选项B:平行测试目录
src/
├── services/
│   ├── user_service.py
│   └── order_service.py
tests/
├── services/
│   ├── test_user_service.py
│   └── test_order_service.py
优势:清晰分离生产代码与测试代码。是大型项目的标准做法。

Advanced Patterns

进阶模式

Pattern 5: Package Initialization

模式5:包初始化

Use
__init__.py
to provide a clean public interface for package consumers.
python
undefined
使用
__init__.py
为包使用者提供简洁的公共接口。
python
undefined

mypackage/init.py

mypackage/init.py

"""MyPackage - A library for doing useful things."""
from .core import MainClass, HelperClass from .exceptions import PackageError, ConfigError from .config import Settings
all = [ "MainClass", "HelperClass", "PackageError", "ConfigError", "Settings", ]
version = "1.0.0"

Consumers can then import directly from the package:

```python
from mypackage import MainClass, Settings
"""MyPackage - 一个用于实现实用功能的库。"""
from .core import MainClass, HelperClass from .exceptions import PackageError, ConfigError from .config import Settings
all = [ "MainClass", "HelperClass", "PackageError", "ConfigError", "Settings", ]
version = "1.0.0"

使用者随后可以直接从包导入:

```python
from mypackage import MainClass, Settings

Pattern 6: Layered Architecture

模式6:分层架构

Organize code by architectural layer for clear separation of concerns.
myapp/
├── api/           # HTTP handlers, request/response
│   ├── routes/
│   └── middleware/
├── services/      # Business logic
├── repositories/  # Data access
├── models/        # Domain entities
├── schemas/       # API schemas (Pydantic)
└── config/        # Configuration
Each layer should only depend on layers below it, never above.
按架构层组织代码,实现清晰的关注点分离。
myapp/
├── api/           # HTTP处理器、请求/响应
│   ├── routes/
│   └── middleware/
├── services/      # 业务逻辑
├── repositories/  # 数据访问
├── models/        # 领域实体
├── schemas/       # API模式(Pydantic)
└── config/        # 配置
每个层应仅依赖于其下方的层,绝不能依赖上方的层。

Pattern 7: Domain-Driven Structure

模式7:领域驱动结构

For complex applications, organize by business domain rather than technical layer.
ecommerce/
├── users/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
├── orders/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
└── shared/
    ├── database.py
    └── exceptions.py
对于复杂应用,按业务领域而非技术层进行组织。
ecommerce/
├── users/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
├── orders/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
└── shared/
    ├── database.py
    └── exceptions.py

File and Module Naming

文件与模块命名

Conventions

约定

  • Use
    snake_case
    for all file and module names:
    user_repository.py
  • Avoid abbreviations that obscure meaning:
    user_repository.py
    not
    usr_repo.py
  • Match class names to file names:
    UserService
    in
    user_service.py
  • 所有文件和模块名称使用
    snake_case
    命名法:
    user_repository.py
  • 避免使用会模糊含义的缩写:使用
    user_repository.py
    而非
    usr_repo.py
  • 类名与文件名匹配:
    UserService
    位于
    user_service.py

Import Style

导入风格

Use absolute imports for clarity and reliability:
python
undefined
使用绝对导入以确保清晰性和可靠性:
python
undefined

Preferred: Absolute imports

推荐:绝对导入

from myproject.services import UserService from myproject.models import User
from myproject.services import UserService from myproject.models import User

Avoid: Relative imports

避免:相对导入

from ..services import UserService from . import models

Relative imports can break when modules are moved or reorganized.
from ..services import UserService from . import models

相对导入在模块被移动或重组时可能会失效。

Best Practices Summary

最佳实践总结

  1. Keep files focused - One concept per file, consider splitting at 300-500 lines (varies by complexity)
  2. Define
    __all__
    explicitly
    - Make public interfaces clear
  3. Prefer flat structures - Add depth only for genuine sub-domains
  4. Use absolute imports - More reliable and clearer
  5. Be consistent - Apply patterns uniformly across the project
  6. Match names to content - File names should describe their purpose
  7. Separate concerns - Keep layers distinct and dependencies flowing one direction
  8. Document your structure - Include a README explaining the organization
  1. 保持文件聚焦 - 每个文件对应一个概念,当代码行数达到300-500行时考虑拆分(根据复杂度有所不同)
  2. 明确定义
    __all__
    - 让公共接口清晰可见
  3. 优先采用扁平化结构 - 仅当存在真正的子领域时才增加层级深度
  4. 使用绝对导入 - 更可靠且更清晰
  5. 保持一致性 - 在项目中统一应用模式
  6. 名称与内容匹配 - 文件名应描述其用途
  7. 分离关注点 - 保持各层独立,依赖关系单向流动
  8. 记录你的结构 - 在README中说明项目组织方式