不同的项目往往依赖同一个包的不同版本,全部装进系统的 Python 会互相冲突。虚拟环境为每个项目提供一套独立的解释器和包目录,互不影响,删除时也只需要删掉对应的目录
Ubuntu 23.04 起,系统自带的pip直接安装包时会报externally-managed-environment错误,这是为了防止破坏系统自身依赖的 Python 包,正确的做法就是在虚拟环境中安装
工具对比
| 工具 | 管理 Python 版本 | 包的来源 | 特点 |
|---|
venv | 不能,使用系统已有的 Python | PyPI | 标准库自带,不需要额外安装,功能最基础 |
conda | 能 | Conda 频道,也可以用pip | 可以安装 CUDA、编译器等非 Python 依赖,环境集中存放 |
uv | 能 | PyPI | 速度快,带锁文件的项目依赖管理,兼容pip的用法 |
venv
venv是 Python 标准库自带的虚拟环境模块,环境就是项目目录下的一个文件夹,习惯上命名为.venv
1
| sudo apt install -y python3-venv
|
1
2
| source .venv/bin/activate
deactivate
|
激活后终端提示符前会出现(.venv),此时的python和pip都指向环境内部,安装的包只存在于该环境中
1
2
| pip install numpy
pip list
|
1
| pip freeze > requirements.txt
|
1
| pip install -r requirements.txt
|
虚拟环境中保存的是绝对路径,移动或重命名项目目录后环境会失效,需要删除后重新创建。.venv不应提交到代码仓库,提交requirements.txt即可
Conda
conda是anaconda发行版中的包管理器,用于安装、更新、卸载软件包,以及创建和管理不同的Python环境。除Anaconda外,也可以使用默认conda-forge频道的Miniforge发行版(Anaconda的defaults频道对组织用户有商业授权限制)
环境管理
1
| conda create --name env
|
1
| conda create --name env python=3.12
|
1
| conda env create -f conda_environment.yaml
|
1
2
| conda activate env
conda deactivate
|
1
| conda create --name env_copy --clone env
|
1
2
| conda env export --name env > conda_environment.yaml
conda env export --name env --from-history > conda_environment.yaml
|
直接导出会包含所有依赖及其构建编号,只能在相同的操作系统上还原;加上--from-history只导出手动安装过的包,适合跨平台共享
1
| conda env remove --name env
|
1
| conda config --set auto_activate_base false
|
包管理
以下命令作用于当前激活的环境,也可以用--name env指定环境
1
2
3
| conda install numpy
conda install numpy=1.26
conda install -c conda-forge opencv
|
1
2
| conda list
conda search numpy
|
1
2
| conda update numpy
conda remove numpy
|
conda环境中可以使用pip安装conda频道中没有的包,但应先用conda安装能安装的包,最后再使用pip,否则conda之后的依赖解析可能会破坏pip安装的包
优化指令
显示配置的来源文件及其内容
1
| conda config --show-sources
|
与conda config --show channels相比,能查看当前环境所读取的配置文件信息
使用 libmamba 求解器
conda 23.10 起默认使用libmamba求解器(即mamba的求解器),无需另外安装mamba即可获得更快的依赖解析。可通过以下命令确认
1
| conda config --show solver
|
如需使用mamba命令本身,官方推荐直接安装Miniforge发行版(自带conda-forge与mamba),不建议在 Anaconda 的base环境中用conda install mamba混装conda-forge的包。mamba的大部分命令与conda相同,但 2.x 版本在部分子命令上存在差异
uv
uv是用 Rust 编写的 Python 包与项目管理工具,把pip、venv、Python 版本管理和依赖锁定合并到了一个命令里,安装包的速度比pip快很多
安装
1
| curl -LsSf https://astral.sh/uv/install.sh | sh
|
安装到~/.local/bin,重新打开终端后生效
管理 Python 版本
uv可以自行下载并管理多个 Python 版本,不依赖系统自带的 Python,也不需要sudo
创建环境或运行项目时,所需的 Python 版本不存在会自动下载
虚拟环境与 pip 接口
uv pip的用法与pip基本一致,适合在已有的requirements.txt工作流中直接替换
1
2
| uv venv
uv venv --python 3.12
|
1
| source .venv/bin/activate
|
1
2
| uv pip install numpy
uv pip install -r requirements.txt
|
1
2
| uv pip list
uv pip freeze > requirements.txt
|
uv pip默认操作当前目录下的.venv,不激活环境也可以使用。uv venv创建的环境中没有pip命令,安装包一律使用uv pip
项目管理
uv推荐的用法是把依赖写进pyproject.toml,由它负责创建环境、解析依赖和生成锁文件,不需要手动激活环境
1
2
| uv init --app --no-package demo
cd demo
|
--app --no-package创建的是只有一个main.py的脚本项目;不加参数时会生成带src/目录、可以被安装的包
| 文件 | 作用 |
|---|
pyproject.toml | 项目信息和依赖列表 |
uv.lock | 锁文件,记录每个依赖解析出的确切版本,应提交到代码仓库 |
.python-version | 项目使用的 Python 版本 |
.venv | 虚拟环境,首次运行时自动创建,不提交到代码仓库 |
1
2
3
| uv add numpy
uv add "numpy>=2.0"
uv add --dev pytest
|
1
2
| uv run main.py
uv run pytest
|
uv run运行前会检查环境与锁文件是否一致,不一致时自动同步,因此不需要激活环境
1
| uv export --format requirements-txt -o requirements.txt
|
运行命令行工具
ruff、black这类命令行工具不属于某个项目,可以用uvx在临时环境中直接运行,不污染任何环境
1
2
| uv tool install ruff
uv tool list
|
镜像与缓存
下载速度慢时可以配置 PyPI 镜像,对所有项目生效
1
2
3
| [[index]]
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true
|
只想对单个项目生效时,在pyproject.toml中把[[index]]写成[[tool.uv.index]]
uv下载过的包保存在全局缓存中,多个环境通过链接共用同一份文件,不会重复占用磁盘
1
2
| uv cache dir
uv cache clean
|
如何选择
- 只是临时装几个包、不想装额外的工具,使用
venv - 需要 CUDA、OpenCV 等带有非 Python 依赖的包,或者要与他人共享完整的运行环境,使用
conda - 新建的纯 Python 项目使用
uv,依赖有锁文件,换一台机器执行uv sync就能得到相同的环境 - 不要在同一个环境里混用多种工具安装包,
conda环境中确实需要pip时放在最后安装