传统 Python 项目经常同时使用 pip 安装包、virtualenv 创建环境,再手工维护 requirements.txt。这套组合可以工作,但开发者必须自己保证虚拟环境、直接依赖和最终安装版本彼此一致。Pipenv 将这些工作收拢到一个命令行工具中,并用 Pipfile 与 Pipfile.lock 分别描述依赖意图和可复现的安装结果。
Pipenv 实际解决了什么
Pipenv 的核心不是换一种方式执行 pip install,而是把依赖管理流程串联起来:
- 自动为项目创建和选择虚拟环境;
- 将正式依赖与开发依赖分开管理;
- 使用
Pipfile记录项目需要哪些包; - 使用
Pipfile.lock锁定具体版本及哈希; - 通过统一命令在虚拟环境中运行程序、测试和工具。
两个文件承担不同职责。Pipfile 更像开发者维护的声明文件,例如允许 Flask 使用某个版本范围;Pipfile.lock 则记录依赖解析后的精确版本。团队通常应同时提交这两个文件,但不应手工修改锁文件。
一个简化的 Pipfile 大致如下:
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
[dev-packages]
pytest = "*"
[requires]
python_version = "3.12"
这里的 [packages] 用于运行时依赖,[dev-packages] 用于测试、格式化和静态检查等开发工具。具体版本会进一步写入 Pipfile.lock。
从空目录启动一个可运行项目
下面可以创建一个最小 Flask 服务。运行前需要安装 Python 3.12;如果使用其他版本,请相应修改 pipenv --python 参数。
先安装 Pipenv。使用 pipx 可以让 Pipenv 自身与业务项目隔离:
python -m pip install --user pipx
python -m pipx ensurepath
pipx install pipenv
重新打开终端后,创建项目并安装依赖:
mkdir pipenv-demo
cd pipenv-demo
pipenv --python 3.12
pipenv install flask
pipenv install --dev pytest
cat > app.py <<'PY'
from flask import Flask, jsonify
app = Flask(__name__)
@app.get('/health')
def health():
return jsonify(status='ok')
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
PY
pipenv run python app.py
在另一个终端中验证服务:
curl http://127.0.0.1:5000/health
预期响应为:
{"status":"ok"}
pipenv run 不要求当前终端先进入虚拟环境,适合脚本和 CI。需要连续执行多条交互式命令时,也可以进入环境:
pipenv shell
python app.py
退出时执行 exit。日常自动化中更推荐显式使用 pipenv run <command>,因为命令依赖哪个环境会更加清楚。
安装、升级与检查依赖
添加带版本范围的包时,可以把约束直接交给 Pipenv:
pipenv install 'requests~=2.32'
pipenv install --dev 'pytest>=8,<9'
这些命令会更新 Pipfile,重新解析依赖,并更新锁文件。查看完整依赖树可以使用:
pipenv graph
如果只修改了 Pipfile,可以显式重新生成锁文件:
pipenv lock
升级依赖前应先检查变更范围,并运行测试。可以这样实践:
pipenv update
pipenv run pytest
git diff -- Pipfile Pipfile.lock
不要只看 Pipfile 是否变化。一次看似简单的顶层依赖升级,可能同时改变多个间接依赖,因此 Pipfile.lock 的差异和测试结果同样重要。
删除依赖时也应通过 Pipenv 操作:
pipenv uninstall requests
pipenv uninstall --dev pytest
如果只是想删除项目对应的虚拟环境,而保留依赖文件,可以执行:
pipenv --rm
之后再次运行 pipenv install,Pipenv 会重建环境。
在 CI 和生产环境中坚持使用锁文件
开发机器可以解析新的依赖版本,部署环境则通常应该安装已经审核过的锁定结果。CI 可以采用下面的流程:
python -m pip install pipenv
pipenv install --dev --deploy --ignore-pipfile
pipenv run pytest
其中:
--dev安装测试等开发依赖;--deploy在锁文件不符合要求时让命令失败,而不是静默继续;--ignore-pipfile要求按照锁文件安装,不重新根据Pipfile解析版本。
生产环境通常不需要开发依赖:
python -m pip install pipenv
pipenv install --deploy --ignore-pipfile
pipenv run python app.py
在已经由容器提供隔离能力、不希望容器内部再创建虚拟环境时,可以考虑安装到容器当前 Python 环境:
pipenv install --system --deploy --ignore-pipfile
--system 会改变安装位置,应只在容器或明确隔离的构建环境中使用,不建议直接对开发机的系统 Python 执行。
采用前的检查清单
Pipenv 适合希望用一个工具统一虚拟环境、依赖声明和锁文件的项目。引入时建议确认以下事项:
- 团队成员和 CI 使用兼容的 Python 版本;
Pipfile与Pipfile.lock都纳入版本控制;- 开发依赖放入
[dev-packages],避免进入生产环境; - CI 使用锁文件安装,并在锁文件过期时立即失败;
- 升级依赖后检查锁文件差异并执行完整测试;
- 不对本机系统 Python 随意使用
--system。
Pipenv 减少的是工具之间的接缝,而不是依赖管理本身的复杂度。对于已有稳定 requirements.txt 流程的项目,迁移收益需要结合团队习惯评估;对于新项目或经常出现环境不一致的问题,它能提供一条更集中、也更容易审查的工作流。