注:以下文章有ChatGPT辅助生成
1. 为什么需要项目管理
1.1 大型 Python 项目的常见痛点
1.1.1 包管理地狱(Dependency Hell)
- 版本冲突:
pip install A
后发现 B 坏了;升级一个库,另一个库的 API 变了。 - 跨平台不一致:Windows 上装得好好的,Linux 服务器上编译不过;macOS 上还要 Homebrew。
- 科学计算/深度学习库难装:
numpy / pytorch / opencv / xgboost
… 这些库往往涉及 C/C++、CUDA、MKL,pip 纯 Python 轮子经常行不通。
1.1.2 业务逻辑引用混乱
- src 乱放,import 乱飞:
from utils import func
到处乱引,重构就爆炸。 - 测试/脚本无法正确引用项目代码:
sys.path.append('../src')
这种“土法上马”长期看不可维护。
1.1.3 与 AI 协作的风险和难度
- AI 生成代码可能随手
pip install
或改动 pyproject:不受控。 - AI 误改项目结构/依赖:比如把业务代码塞在根目录、删除
__init__.py
、或在 notebook 里直接 import 本地文件。 - 环境不可复现:AI 生成的说明往往缺少锁定版本或构建脚本,团队协同困难。
- AI上下文限制:由于AI的上下文长度限制,使代码应尽量拆细到多个文件,这使得工程的文件量增加很多。有必要使这些文件能以一种经由实践检验的好方式来组织,使人和AI都能很好驾驭。
1.2 结论:需要一套“硬件 + 软件”双保险
- Conda:解决“硬件层/二进制层”的依赖(Python 解释器版本、CUDA、MKL、C 库等)。
- Poetry:解决“软件层/纯 Python 层”的依赖与打包(锁定版本、发布、依赖解析)。
- 规范的项目结构:让 IDE、测试框架、CI/CD、AI 代码生成都能遵守共同的路径与规则。
2. 工具介绍
2.1 Conda:环境与二进制依赖管理器
- 特点:
- 创建隔离环境(可指定 Python 版本)。
- 安装预编译的科学计算大包,兼容 Windows/Linux/macOS。
- 支持非 Python 依赖(如
cuda
,ffmpeg
,graphviz
)。
- 适用场景:数据科学 / 深度学习 / 需要复杂底层依赖的项目。
2.2 Poetry:现代化 Python 依赖 & 构建管理器
- 特点:
- 使用
pyproject.toml
管理依赖和项目元信息。 - 自动生成
poetry.lock
,确保依赖版本一致。 - 提供
poetry build
/poetry publish
,方便打包发布。 - 与 pip/venv 兼容,也可以“接管”已有环境。
- 使用
- 适用场景:任何需要:版本锁定、可发布、团队协作、CI/CD 的 Python 项目。
2.3 为什么组合使用?
需求/能力 | Conda | Poetry | 组合效果 |
---|---|---|---|
安装 CUDA / MKL / C 库 | ✅ | ❌ | ✅(Conda 负责) |
锁定纯 Python 依赖版本 | ❌ | ✅ | ✅(Poetry 负责) |
构建 & 发布 PyPI 包 | ❌ | ✅ | ✅ |
跨平台一致性 | ✅ | ✅ | ✅ |
团队协作 / CI 可复现性 | ✅ | ✅ | ✅ |
2.4 Pytest:强大且灵活的 Python 测试框架
- 特点:
- 支持简单函数式测试,也支持类和夹具(fixture)的结构化测试。
- 自动发现以
test_
开头的函数 / 文件 / 类,易于组织测试代码。 - 提供强大的断言重写机制,错误信息清晰、可读。
- 支持参数化、跳过、预期失败等高级测试控制。
- 丰富的插件生态(如
pytest-cov
、pytest-xdist
),便于扩展和集成。
- 适用场景:适用于任何需要高可读性、易扩展、适配 CI 流程的 Python 测试项目,尤其适合中大型项目的单元测试与集成测试需求。
3. 完整项目示例:从 0 到 1
我们来搭建一个最小可运行的示例项目:my_project
3.1 Conda 环境搭建
1)创建环境:
# 创建名为 qs的 Conda 环境并安装基础包
conda create -n qspython=3.11 numpy pandas -y
conda activate qs
2)生成 environment.yml(可选,但推荐)
进入项目根目录并运行
conda env export --from-history > environment.yml
--from-history
只导出你手动安装的包,避免导出一大堆依赖树。
示例 environment.yml
:
name: qs
channels:
- conda-forge
dependencies:
- python=3.11
- numpy
- pandas
- pip # 让你还能用 pip 安装少量 PyPI 包
3.2 Poetry 环境搭建
1)在 Conda 环境中安装 Poetry(推荐用 pip 安装到当前环境):
pip install poetry
2)让 Poetry 使用当前 Conda 环境(关键):
poetry config virtualenvs.create false
这行的意思是:Poetry 不再创建自己的 venv,而是复用你激活的 Conda 环境。
3)初始化 pyproject.toml:
poetry init
# 按提示填写:项目名、版本、依赖等,也可以后续手动编辑
或者直接编辑一个最小示例:
[tool.poetry]
name = "quant-strategy-v2"
version = "0.1.0"
description = ""
authors = ["Raytto <306483372@qq.com>"]
readme = "README.md"
packages = [{ include = "qs", from = "src" }]
# optional: if you later publish to PyPI
# license = "MIT"
[tool.poetry.dependencies]
python = "^3.11"
[tool.poetry.group.dev.dependencies]
pytest = "^8.4.1"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
如果指定了readme = "README.md"
,则需要在项目目录创建一个README.md
"# quant-strategy-v2" | Out-File -Encoding utf8 README.md
如果指定了 packages = [{ include = "qs", from = "src" }]
,则需要创建一下目录和文件:
├── src/
│ └── qs/
│ ├── __init__.py
│ └── main.py
│ └── core.py
4)安装依赖:
poetry install
# 或者新增依赖:poetry add requests
# 新增开发依赖:poetry add --group dev pytest
3.3 项目文件结构
my_project/
├── environment.yml # Conda 环境定义
├── pyproject.toml # Poetry 配置
├── poetry.lock # Poetry 锁文件(自动生成)
├── README.md
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── main.py
│ └── core.py
├── tests/
│ └── test_core.py
└── notebooks/
└── demo.ipynb
3.4 最小可运行实例
src/qs/core.py
def add(a: int, b: int) -> int:
return a + b
tests/test_core.py
from qs.core import add
def test_add():
assert add(1, 2) == 3
dev环境下安装 pytest :
poetry add --dev pytest
运行测试:
poetry run pytest -q
运行模块:
python -c "from qs.core import add; print(add(3, 4))"
3.5 每次重新打开工程时需要做什么?
- 打开终端,激活 Conda 环境:
conda activate qs
- (首次)同步 Poetry 依赖:
poetry install
- 运行测试 / 脚本 / notebook。
注:常规开发周期里只要记得 conda activate
,Poetry 的安装只在依赖更新后需要执行一次。
3.6 从 Git 克隆后如何准备环境?
- 克隆代码:
git clone git@github.com:yourname/my_project.git cd my_project
- 用
environment.yml
创建环境- 如果提供了):
conda env create -f environment.yml conda activate my_project
- 如果没有
environment.yml
,你也可以手动创建:conda create -n my_project python=3.11 -y conda activate my_project
- 如果提供了):
- 安装 Poetry(若环境首次使用):
pip install poetry poetry config virtualenvs.create false
- 安装项目依赖:
poetry install # 会根据 poetry.lock 安装精确版本
- 运行测试验证:
pytest -q
4. 最佳实践与小贴士
- Conda 安装“硬依赖”(科学计算、GPU、系统库),Poetry 管理“软依赖”(纯 Python 包)。
- 只在必要时使用
pip
:- Conda 找不到的包,用
pip install
;但尽量仍通过 Poetry (poetry add
) 来锁定版本。
- Conda 找不到的包,用
- 保持
src/
布局:packages = [{ include = "my_package", from = "src" }]
- 测试只需
from my_package import xxx
,无需改sys.path
。
- 避免把业务代码放在 notebooks 中:notebook 应调用包函数,确保逻辑可测试、可复用。
- 把 AI 当实习生,用规范“约束”它:
- 给 AI 明确的项目结构说明和依赖管理原则。
- 设定自动化检查(pre-commit、CI)来防止不合规代码进入主分支。
- 在 CI/CD 中:
- 用
conda-lock
或者导出 environment.yml 来固定 Conda 版本。 - 用
poetry install --no-root
安装依赖;需要时poetry build
+pip install dist/*.whl
。
- 用
5. 其他相关实践
5.1 把当前环境注册为ipykernel
方便notebook使用.
在对应conda虚拟环境中
vpoetry config virtualenvs.create false # 关键:复用当前 Conda 环境
# 3. 安装项目依赖
poetry install
c # 若还没装 ipykernel
# 4. 注册为 Jupyter Kernel
poetry run python -m ipykernel install --user --name qs --display-name "my_quant_strategy"