3、Python与依赖管理:版本、环境与依赖的“三角关系”
说实话,Python 这门语言本身不难学。但真正让新手头疼的,往往是环境问题。
你想想看,一个项目用 Python 3.8,另一个项目必须用 3.10。一个项目依赖 A 库的 1.0 版本,另一个项目却需要 2.0 版本。如果全装在一个系统里,那不乱套了吗?
我刚开始做机器学习那会儿,就吃过这个亏。有一次跑一个老项目,死活装不上依赖,最后发现是系统 Python 版本太高,跟项目不兼容。折腾了两天,才意识到是环境管理没做好。
所以这一章,咱们就把 Python 版本管理、虚拟环境和依赖管理这三件事彻底讲清楚。说白了,就是让你能随心所欲地切换 Python 版本、隔离项目环境、精准控制依赖包。
3.1 Python 版本管理:用 pyenv 搞定多版本共存
系统自带的 Python 版本通常只有一个。比如 macOS 可能自带 Python 2.7,Ubuntu 可能自带 Python 3.8。但你的项目可能需要 3.9、3.10 甚至 3.11。
怎么办?用 pyenv。
pyenv 是一个 Python 版本管理工具。它不会动你的系统 Python,而是让你在用户级别安装和管理多个 Python 版本,并且可以随时切换。
安装 pyenv
在 macOS 或 Linux 上,推荐用官方安装脚本:
curl https://pyenv.run | bash
安装完成后,记得把以下内容加到你的 ~/.bashrc 或 ~/.zshrc 里:
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
然后重新加载配置文件:
source ~/.bashrc
常用命令
安装好之后,你就可以用 pyenv 来管理 Python 版本了。我个人习惯用这些命令:
pyenv install --list:查看所有可安装的 Python 版本pyenv install 3.10.12:安装指定版本pyenv versions:查看已安装的所有版本pyenv global 3.10.12:设置全局默认版本pyenv local 3.9.18:在当前目录设置局部版本(会生成 .python-version 文件)
pyenv local。这样团队成员 clone 项目后,只要安装了 pyenv,就能自动切换到正确的 Python 版本。
pyenv 的工作原理
pyenv 通过修改 PATH 环境变量来拦截 Python 命令。它会在 PATH 前面插入一个 shims 目录,这个目录里有一些轻量级的可执行文件,它们会根据当前目录的 .python-version 文件来决定调用哪个版本的 Python。
嗯,说白了就是“狸猫换太子”。你执行 python 命令时,实际上执行的是 pyenv 的 shim,它再帮你转发到真正的 Python 可执行文件。
3.2 虚拟环境:venv 与 conda 的抉择
有了 pyenv,你可以切换 Python 版本了。但同一个 Python 版本下,不同项目可能依赖不同版本的包。这时候就需要虚拟环境。
虚拟环境,说白了就是一个隔离的 Python 运行环境。每个虚拟环境都有自己的 site-packages 目录,里面装着这个项目专属的依赖包。
venv:Python 自带的轻量级方案
从 Python 3.3 开始,标准库就自带了 venv 模块。用法很简单:
# 创建虚拟环境
python -m venv myenv
# 激活虚拟环境(Linux/macOS)
source myenv/bin/activate
# 激活虚拟环境(Windows)
myenv\Scripts\activate
# 退出虚拟环境
deactivate
激活后,你会发现命令行前面多了 (myenv) 的提示。这时候你安装的所有包,都会装到这个虚拟环境里,不会影响系统全局。
conda:数据科学家的瑞士军刀
conda 是 Anaconda 发行版自带的包管理器和环境管理器。它跟 venv 最大的区别是:conda 不仅能管理 Python 包,还能管理非 Python 的依赖,比如 C 库、CUDA 工具包等。
我在做深度学习项目时,经常遇到这种情况:某个库需要特定版本的 CUDA,而另一个库又需要另一个版本。用 conda 就可以轻松创建两个独立的环境,每个环境装不同的 CUDA 版本。
# 创建 conda 环境,指定 Python 版本
conda create -n myenv python=3.10
# 激活环境
conda activate myenv
# 安装包
conda install numpy pandas
# 退出环境
conda deactivate
# 删除环境
conda remove -n myenv --all
| 特性 | venv | conda |
|---|---|---|
| 适用范围 | 仅 Python 包 | Python 包 + 非 Python 依赖 |
| 性能 | 轻量,创建快 | 较重,创建稍慢 |
| 依赖解析 | 依赖 pip | 自带依赖解析器 |
| 适用场景 | 通用 Python 项目 | 数据科学、机器学习 |
pip install,但不要频繁混用。
3.3 依赖管理:pip 与 poetry 的对比
有了虚拟环境,接下来就是管理依赖包了。最传统的方式是用 pip 配合 requirements.txt。但近年来,poetry 越来越流行,它提供了更现代化的依赖管理方案。
pip + requirements.txt:经典方案
这是最基础的方式。你可以在项目根目录下创建一个 requirements.txt 文件,列出所有依赖:
numpy==1.24.3
pandas==2.0.3
scikit-learn==1.3.0
torch==2.0.1
然后执行:
pip install -r requirements.txt
导出当前环境的依赖:
pip freeze > requirements.txt
pip freeze 会导出所有已安装的包,包括那些间接依赖。这会导致 requirements.txt 非常臃肿,而且无法区分“直接依赖”和“间接依赖”。
poetry:现代化的依赖管理
poetry 解决了 pip 的很多痛点。它使用 pyproject.toml 文件来管理项目元数据和依赖,并且会自动生成 poetry.lock 文件来锁定所有依赖的精确版本。
安装 poetry:
curl -sSL https://install.python-poetry.org | python3 -
初始化一个新项目:
poetry new myproject
cd myproject
或者在已有项目中初始化:
poetry init
添加依赖:
poetry add numpy pandas
poetry add --dev pytest # 开发依赖
安装所有依赖:
poetry install
生成的 pyproject.toml 文件长这样:
[tool.poetry]
name = "myproject"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.10"
numpy = "^1.24.3"
pandas = "^2.0.3"
[tool.poetry.dev-dependencies]
pytest = "^7.4.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api
poetry.lock 文件能确保团队所有成员和 CI/CD 环境都使用完全相同的依赖版本,避免“在我机器上能跑”的尴尬。
3.4 知识体系总览
下面这张图,帮你理清 Python 环境管理的整体脉络:
3.5 避坑指南与个人经验
最后,分享几个我踩过的坑,希望能帮你少走弯路。
- 不要用 sudo pip install:我曾经为了省事,直接
sudo pip install装包,结果把系统 Python 的环境搞乱了,最后不得不重装系统。记住,永远在虚拟环境里装包。 - pyenv 和 conda 不要混用:pyenv 管理 Python 版本,conda 管理环境。如果你用 conda,就不需要 pyenv 了,因为 conda 本身就能指定 Python 版本。
- poetry.lock 要提交到版本控制:这个文件记录了所有依赖的精确版本。如果不提交,团队成员可能装到不同版本的依赖,导致“在我机器上能跑”的问题。
- 定期清理不用的虚拟环境:时间久了,你的电脑里可能躺着几十个虚拟环境,占用大量磁盘空间。我每个月都会用
conda env list或ls ~/.pyenv/versions检查一下,删掉不用的。
好了,这一章的内容就到这里。Python 环境管理看似琐碎,但它是机器学习平台搭建的基石。把这三件事理顺了,后面的开发会顺畅很多。
公众号:蓝海资料掘金营,微信deep3321