3. 依赖管理与包安装:pip、requirements.txt、poetry、conda环境导出与复现
在补货计划系统的工程落地中,依赖管理是保障环境一致性与可复现性的基石。补货算法通常依赖数值计算(NumPy、Pandas)、运筹优化(SciPy、OR-Tools)、机器学习(scikit-learn)以及数据库驱动(SQLAlchemy、psycopg2)。若依赖版本混乱,轻则接口不兼容导致运行时错误,重则算法结果偏差影响补货决策。本节系统梳理四种主流依赖管理方案,并给出供应链场景下的选型建议。
3.1 依赖管理方案对比
| 方案 | 核心机制 | 锁定文件 | 环境隔离 | 适用场景 |
|---|---|---|---|---|
| pip + requirements.txt | 逐行声明依赖,pip install 解析安装 | 无严格锁定(可配合 pip freeze) | 需配合 venv/virtualenv | 快速原型、小型项目、CI/CD 基础镜像 |
| Poetry | pyproject.toml 声明 + poetry.lock 锁定 | poetry.lock(精确哈希) | 内置虚拟环境管理 | 中大型项目、库发布、团队协作 |
| Conda | environment.yml 声明 + 二进制包管理 | environment.yml(含版本号) | 内置环境隔离 | 跨平台、非 Python 依赖(如 C++ 库)、数据科学 |
供应链选型建议: 若补货系统仅依赖纯 Python 包,优先使用 Poetry 保证锁定精度;若涉及 OR-Tools、Gurobi 等含 C++ 扩展的求解器,或需要在 Windows/Linux 间切换开发与生产环境,推荐 Conda 管理二进制依赖。
3.2 pip + requirements.txt:基础但需谨慎
requirements.txt 是最直接的依赖声明方式,但直接使用 pip freeze > requirements.txt 会输出当前环境的全部包(含间接依赖),导致跨平台兼容性问题。推荐采用分层声明策略:
# requirements-base.txt —— 核心依赖,不锁版本下限
numpy>=1.21
pandas>=1.3
scipy>=1.7
# requirements-prod.txt —— 生产锁定版本
-r requirements-base.txt
numpy==1.23.5
pandas==1.5.3
scipy==1.9.3
or-tools==9.6
# requirements-dev.txt —— 开发额外工具
-r requirements-prod.txt
pytest==7.2.0
black==22.12.0
pre-commit==3.0.0
避坑: 不要在 requirements.txt 中使用
== 锁定所有间接依赖,否则在 Python 版本升级或操作系统变更时极易出现依赖冲突。仅锁定直接依赖的精确版本,间接依赖由 pip 的解析器自动选择兼容版本。
3.3 Poetry:现代依赖管理的工程实践
Poetry 通过 pyproject.toml 统一管理项目元数据与依赖,poetry.lock 文件记录每个包及其依赖的精确哈希值,确保跨环境完全一致。补货计划项目典型配置如下:
[tool.poetry]
name = "replenishment-engine"
version = "0.1.0"
description = "补货计划核心算法引擎"
[tool.poetry.dependencies]
python = "^3.9"
numpy = "^1.23"
pandas = "^1.5"
scipy = "^1.9"
or-tools = "^9.6"
sqlalchemy = "^2.0"
psycopg2-binary = "^2.9"
[tool.poetry.dev-dependencies]
pytest = "^7.2"
pytest-cov = "^4.0"
mypy = "^0.991"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
常用命令速查:
poetry add numpy—— 添加依赖并自动更新 lock 文件poetry install—— 根据 lock 文件安装精确环境poetry export -f requirements.txt --output requirements.txt—— 导出为 requirements.txt 供 Docker 使用
3.4 Conda 环境导出与复现
当补货系统依赖 Gurobi、CPLEX 等商业求解器或 OpenBLAS 等底层数值库时,Conda 的二进制包管理优势明显。环境导出与复现流程如下:
# 导出当前环境(含精确版本号)
conda env export -n replenishment_env > environment.yml
# 从 yml 文件复现环境
conda env create -f environment.yml
# 跨平台导出(仅显式安装的包,不含 build 标识)
conda env export -n replenishment_env --no-builds > environment.yml
environment.yml 示例:
name: replenishment_env
channels:
- conda-forge
- defaults
dependencies:
- python=3.9.16
- numpy=1.23.5
- pandas=1.5.3
- scipy=1.9.3
- or-tools=9.6
- sqlalchemy=2.0.4
- psycopg2=2.9.5
- pip
- pip:
- gurobipy==10.0.1
关键差异: Conda 的 environment.yml 可以同时管理 conda 包和 pip 包(通过 pip 子节),而 Poetry 仅管理 pip 可安装的包。若项目混合使用 conda 和 pip 源,务必在 yml 中明确区分,避免复现时 pip 包版本漂移。
3.5 依赖管理流程与工程落地
下图展示了补货计划系统中依赖管理的完整生命周期,从开发环境搭建到生产部署的版本一致性保障:
3.6 工程落地检查清单
- 锁定文件入版本库: poetry.lock 或 environment.yml 必须提交至 Git,禁止在 .gitignore 中忽略。
- CI 流水线一致性校验: 在 CI 中执行
poetry lock --check或conda env export --no-builds | diff - environment.yml,防止依赖漂移。 - Docker 分层缓存优化: 先复制锁定文件安装依赖,再复制业务代码,利用 Docker 缓存层加速构建。
- Python 版本固定: 在 pyproject.toml 或 environment.yml 中明确指定 Python 主次版本(如 3.9.x),避免隐式升级导致兼容性问题。
- 私有包索引配置: 若补货系统依赖内部算法库,在 Poetry 中配置
[[tool.poetry.source]]或在 Conda 中配置自定义 channel。
生产环境最佳实践: 建议在 Dockerfile 中使用多阶段构建,第一阶段用 Poetry 安装依赖并导出 requirements.txt,第二阶段基于精简基础镜像(如 python:3.9-slim)仅安装生产依赖,最终镜像体积可减少 40%-60%。