Python 项目结构
良好的项目结构让代码易于维护、测试和分发。Python 社区有成熟的最佳实践。
标准项目结构
推荐布局(src layout):
my_project/
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ ├── test_core.py
│ └── test_utils.py
├── docs/
│ └── index.md
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore关键组件:
src/:源代码目录(推荐)tests/:测试代码docs/:文档pyproject.toml:项目配置README.md:项目说明LICENSE:许可证
src layout vs flat layout
src layout(推荐)
my_project/
├── src/
│ └── my_package/
│ └── __init__.py
└── tests/优点:
- 强制安装后测试(避免导入本地未安装版本)
- 清晰的命名空间
- 避免测试导入冲突
flat layout
my_project/
├── my_package/
│ └── __init__.py
└── tests/缺点:
- 可能导入本地代码而非安装版本
- 测试可能通过但安装后失败
init.py 的作用
标记目录为 Python 包:
python
# src/my_package/__init__.py
"""My Package - 一个示例包"""
__version__ = "0.1.0"
from .core import main_function
from .utils import helper_function
__all__ = ["main_function", "helper_function"]Python 3.3+:空目录也可以是包(namespace package),但显式 __init__.py 更清晰。
虚拟环境
隔离项目依赖,避免冲突。
venv(标准库)
bash
# 创建虚拟环境
python3 -m venv venv
# 激活(Linux/macOS)
source venv/bin/activate
# 激活(Windows)
venv\Scripts\activate
# 安装依赖
pip install requests pytest
# 退出
deactivatevirtualenv(第三方)
bash
pip install virtualenv
virtualenv venv
source venv/bin/activate选择:venv 是标准库,优先使用。
依赖管理
requirements.txt(传统)
txt
requests==2.31.0
pytest>=7.0.0
black~=23.0bash
pip install -r requirements.txt
pip freeze > requirements.txtpyproject.toml(现代,推荐)
toml
[project]
name = "my-package"
version = "0.1.0"
description = "A sample package"
requires-python = ">=3.10"
dependencies = [
"requests>=2.31.0",
"click>=8.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"black>=23.0",
"mypy>=1.0",
]
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"安装:
bash
# 安装包
pip install -e .
# 安装开发依赖
pip install -e ".[dev]"pyproject.toml vs setup.py
| 特性 | pyproject.toml | setup.py |
|---|---|---|
| 标准 | PEP 621(现代) | 传统 |
| 格式 | 声明式(TOML) | 命令式(Python) |
| 推荐 | ✅ 新项目 | 遗留项目 |
迁移:
python
# setup.py(旧)
from setuptools import setup
setup(
name="my-package",
version="0.1.0",
install_requires=["requests"],
)toml
# pyproject.toml(新)
[project]
name = "my-package"
version = "0.1.0"
dependencies = ["requests"]项目模板
cookiecutter
bash
pip install cookiecutter
# 使用模板
cookiecutter https://github.com/audreyr/cookiecutter-pypackage
# 回答提示创建项目手动创建
bash
mkdir my_project
cd my_project
mkdir -p src/my_package tests docs
touch src/my_package/__init__.py
touch tests/__init__.py
touch pyproject.toml README.md LICENSE实战案例:创建完整项目
bash
# 1. 创建结构
mkdir calculator_project
cd calculator_project
mkdir -p src/calculator tests
# 2. 源代码
cat > src/calculator/__init__.py << 'EOF'
"""Simple calculator package"""
__version__ = "0.1.0"
from .operations import add, subtract, multiply, divide
__all__ = ["add", "subtract", "multiply", "divide"]
EOF
cat > src/calculator/operations.py << 'EOF'
def add(a: float, b: float) -> float:
return a + b
def subtract(a: float, b: float) -> float:
return a - b
def multiply(a: float, b: float) -> float:
return a * b
def divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
EOF
# 3. 测试
cat > tests/test_operations.py << 'EOF'
from calculator.operations import add, divide
import pytest
def test_add():
assert add(2, 3) == 5
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(10, 0)
EOF
# 4. 配置
cat > pyproject.toml << 'EOF'
[project]
name = "calculator"
version = "0.1.0"
requires-python = ">=3.10"
[project.optional-dependencies]
dev = ["pytest>=7.0"]
EOF
# 5. 安装和测试
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
pytest小结
- src layout 是推荐的项目结构
- pyproject.toml 替代 setup.py(PEP 621)
- 虚拟环境 隔离项目依赖
- init.py 标记包并定义公共 API
- 项目模板 加速新项目创建
下一节学习 测试基础。
参考:PEP 621 – Python Project Metadata
练习:答案