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) 的提示。这时候你安装的所有包,都会装到这个虚拟环境里,不会影响系统全局。

核心要点: venv 是 Python 官方推荐的方案,轻量、简单、无外部依赖。如果你的项目不需要复杂的依赖管理,venv 完全够用。

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 项目 数据科学、机器学习
注意: 我曾经遇到过 conda 和 pip 混用导致环境崩溃的情况。建议尽量只用一种包管理器。如果非要用 pip 安装 conda 源里没有的包,记得先安装 pip,然后用 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。它把版本管理、依赖管理和打包发布都统一了。而且 poetry.lock 文件能确保团队所有成员和 CI/CD 环境都使用完全相同的依赖版本,避免“在我机器上能跑”的尴尬。

3.4 知识体系总览

下面这张图,帮你理清 Python 环境管理的整体脉络:

Python 环境管理知识体系 Python 版本管理 pyenv 虚拟环境 venv / conda 依赖管理 pip / poetry pyenv install / global / local venv conda pip poetry 最佳实践流程 1. 用 pyenv 安装并切换到项目所需的 Python 版本 2. 用 poetry 初始化项目,自动创建虚拟环境 3. 用 poetry add 管理依赖,用 poetry.lock 锁定版本

3.5 避坑指南与个人经验

最后,分享几个我踩过的坑,希望能帮你少走弯路。

  • 不要用 sudo pip install:我曾经为了省事,直接 sudo pip install 装包,结果把系统 Python 的环境搞乱了,最后不得不重装系统。记住,永远在虚拟环境里装包。
  • pyenv 和 conda 不要混用:pyenv 管理 Python 版本,conda 管理环境。如果你用 conda,就不需要 pyenv 了,因为 conda 本身就能指定 Python 版本。
  • poetry.lock 要提交到版本控制:这个文件记录了所有依赖的精确版本。如果不提交,团队成员可能装到不同版本的依赖,导致“在我机器上能跑”的问题。
  • 定期清理不用的虚拟环境:时间久了,你的电脑里可能躺着几十个虚拟环境,占用大量磁盘空间。我每个月都会用 conda env listls ~/.pyenv/versions 检查一下,删掉不用的。

好了,这一章的内容就到这里。Python 环境管理看似琐碎,但它是机器学习平台搭建的基石。把这三件事理顺了,后面的开发会顺畅很多。


公众号:蓝海资料掘金营,微信deep3321