包括两部分:

  • pip:包下载安装
  • venv:虚拟环境管理

在部分 Linux 发行版(例如 Ubuntu)中即使系统自带 Python,也可能只是包括了最基础的功能,并不包括 pip 和 venv,需要单独下载安装

1
sudo apt-get install python3-pip python3-venv

这些内容在不同的系统(Windows/Linux)中的实现细节各有不同,在不同的 shell(pwsh/bash/fish)中,对应的脚本实现也有差异,下面以 Linux + bash 为主,也会考虑 Windows + pwsh 的情况。

pip

基本使用

使用 pip 可以安装 Python 包,常见形式为

1
pip install <package_name>

例如安装进度条 tqdm

1
pip install tqdm

pip 会自动处理包的版本要求和依赖关系,依赖关系在不同系统下可能存在差异,例如:

  • 在 Linux 上只会安装 tqdm 自身;
  • 在 Windows 上会自动安装两个包:colorama, tqdm,前者是 tqdm 的依赖。

但是 pip 在卸载时并不能自动处理这种依赖关系,而是采用了非常保守的策略:永远不会自动卸载依赖,例如卸载 tqdm 不会导致它的依赖包 colorama 被卸载,用户必须手动操作。

卸载指定的包

1
pip uninstall tdqm

列出当前所有的包

1
pip list

升级指定的包

1
2
3
pip install --upgrade requests
# or
pip install -U requests

可以在下载或升级时指定包的版本

1
pip install requests==2.31.0

由于各个包之间可能存在复杂的依赖关系,批量安装和分别安装时会有不一样的结果:

  • 批量安装:pip 会同时解析所有依赖,找到兼容的版本
  • 分别安装:逐个安装,可能产生冲突或依赖覆盖

因此建议尽量一次性安装多个包,而不是逐个安装。

注意:

  • pip 安装的包默认会存放在特定位置的 site-packages/ 目录(位置直接与当前 Python 解释器的位置有关,也就是与当前环境有关)。
  • pip 本质上仍然是一个 Python 包,同名的可执行文件只是调用入口,实际会调用 site-packages/pip/ 目录中的内容。
  • 在使用时 pip 命令时要注意当前使用的是哪个环境(或虚拟环境)中的 pip。
  • 由于 Python 本身是一个脚本语言,它的包管理器 pip 不仅可以提供用户需要的库,实际上也可以直接提供可执行文件,作为 apt/pacman 等系统包管理器的替代。

pip 配置

pip 可以切换镜像源,临时修改可以通过添加 -i 选项实现,例如

1
pip install -i https://pypi.mirrors.ustc.edu.cn/simple numpy

持续性修改

1
pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/simple

在 Linux 中,这里相当于修改配置文件 ~/.config/pip/pip.conf

1
2
[global]
index-url = https://mirrors.ustc.edu.cn/pypi/simple

安装方式

除了通过 PyPi 进行安装之外,pip 还支持很多安装方式,下面分别介绍。

可以通过 Github 仓库安装:(包括 HTTPS 和 SSH)

1
2
3
pip install git+https://github.com/user/repo.git

pip install git+ssh://git@github.com/user/repo.git

当然这里要求该仓库的内容符合 Python 包的格式标准,例如有 setup.py 文件或者 pyproject.toml 等。

这里还可以指定 Git 仓库的分支或 tag

1
2
3
pip install git+https://github.com/user/repo.git@main

pip install git+https://github.com/user/repo.git@2.3.0

注意这里 pip 不会通过 commit 信息判断版本,而是基于 pip 包的版本号信息判断是否需要更新。

可以通过本地 Git 仓库安装:

1
pip install path/to/local/repo

可以通过 .tar.gz 或 .zip 文件进行源码安装:(也支持压缩包的 URL)

1
pip install /path/to/package.tar.gz

显然这里也要求压缩包中的内容符合 Python 包的格式标准)

此外,还可以使用 Python 的 wheel 文件(后缀 .whl)进行模块安装,wheel 文件是被设计替代源码压缩包的二进制文件,它相比于压缩包的优势是已经包含了所有编译好的二进制文件,因此安装速度更快,并且可以避免一些编译问题。

环境导出和恢复

我们可以使用 requirements.txt 记录当前环境(或虚拟环境)的第三方依赖,例如

1
2
3
4
5
numpy
matplotlib

bibtexparser==1.4.4
pyparsing==3.3.2

在其中既可以指定版本,也可以忽略版本(不建议)。

pip 使用如下命令可以导出当前的所有依赖(包括具体的版本),并保存到文件中,方便下次在别的位置安装

1
pip freeze > requirements.txt

可以在其它位置通过该 requirements.txt 文件安装所有的依赖,从而恢复相同的环境(或虚拟环境)

1
pip install -r requirements.txt

venv

venv 是 Python 提供的一个模块,用于创建隔离的虚拟环境来管理不同项目的依赖关系,每一个虚拟环境存储于一个目录下,但是并不限于在这个目录下使用,实际可以在任何其它位置激活和使用这个虚拟环境。

创建虚拟环境

在当前目录下创建一个名为 myenv 的虚拟环境

1
python -m venv myenv

按照习惯,虚拟环境的文件夹通常被设置为 .venvvenv。(最好不要改动,否则还需要在 IDE 或者 shell 中进行额外的适配)

这个命令会在指定目录下创建一套 Python 运行时,通常包括以下几个关键部分:

  • bin/:包含一个虚拟的 Python 解释器(可执行文件)和 pip 以及命令脚本(针对各个shell);
  • lib/pythonX.Y/site-packages/:存放该虚拟环境下所有的 Python 包,初始情况下可能只有 pip;
  • include/:包含C语言头文件,用于在该虚拟环境中进行扩展编译。

注:

  • 这里呈现的是 Linux 中的目录结构,对于 Windows 存在一些细微区别。在 Ubuntu 中设置了 lib64/ -> lib/
  • 虚拟环境是由当前使用的 Python 解释器创建的,虚拟环境中虽然有一个名为 Python 或 Python3 的解释器,但是实质上还在使用创建时对应的 Python 解释器。
  • 虚拟环境不等于完整的 Python 运行时,只是改变了 site-packages 以隔离第三方依赖,虚拟环境不能摆脱创建时使用的 Python 运行时而独立存在。

虚拟环境有一个关键的配置信息文件 pyvenv.cfg,其中记录了 Python 版本信息,创建时的命令等信息,大致内容形如:

1
2
3
4
5
home = /home/xxx/miniconda3/bin
include-system-site-packages = false
version = 3.12.1
executable = /home/xxx/miniconda3/bin/python3.12
command = /home/xxx/miniconda3/bin/python -m venv /home/xxx/test/myvenv

在第一次创建虚拟环境之后,习惯上会在下载依赖之前更新一下 pip

1
2
3
python -m pip install --upgrade pip
# or
pip install --upgrade pip -q

venv 创建的虚拟环境会自带 pip,但是 uv 创建的虚拟环境就是不包含 pip 的。

激活、退出虚拟环境

虚拟环境所涉及的命令脚本实际上分别提供了 bash,cmd 和 pwsh 这几个版本,下面的讨论主要以 Linux 为例。

执行激活脚本可以激活(当前目录下的)虚拟环境,具体的激活命令与当前使用的 shell 相关,例如

1
2
3
4
5
6
7
8
# windows pwsh
.\myenv\Scripts\Activate(.ps1)

# linux bash
source myenv/bin/activate

# linux fish
source myenv/bin/activate.fish

说明:

  • 在 Linux 中,不能直接执行对应脚本(因为这个脚本没有执行权限),而且只有通过 source(或 .)启动后才会对当前进程有效;(在 Windows 中不存在这种问题)
  • 也可以激活和使用其它目录下的虚拟环境,只需要相应调整命令中的路径即可。

激活环境之后,shell 的命令行提示符通常会变化,自动提示当前虚拟环境的名称,通常是当前项目目录的名称,例如

1
(myenv) user@xxx$

使用 deactivate 命令可以退出当前的虚拟环境

1
deactivate

deactivate 可能是通过单独的 shell 脚本提供,也可能是通过定义的 shell 函数提供。

激活虚拟环境实际上就是调用了对应目录中的激活脚本,执行了一些简单操作,主要包括:

  • 修改环境变量 PATH,将当前目录添加到环境遍历路径的开头,确保 pythonpip 等命令会优先找到当前虚拟环境中的 Python 解释器,这同时会把对应的 site-packages/ 目录添加到模块搜索路径中,确保可以成功导入当前环境中所安装的包;
  • 修改环境变量 VIRTUAL_ENV 记录当前的虚拟环境;
  • 修改当前 shell 的命令行提示符;(受到 VIRTUAL_ENV_DISABLE_PROMPT 环境变量控制)
  • 提供一个 deactivate 命令,作用就是将 activate 所做的修改撤销。

退出激活环境则是撤销了上述过程的影响。

如果要删除虚拟环境,直接删除虚拟环境对应的整个目录即可。

不建议把整个虚拟环境目录在文件系统中移动,venv 虚拟环境在移动后可能出现问题。