深入理解 Python 虚拟环境
前言:Python 作为一个优秀的解释型语言,在各个计算机细分领域都有着广泛的运用。然而 Python 不同版本之间的细微不兼容性使得 Python 解释器、第三方库的管理变得很困难。
为了解决依赖问题,Python 社区发明了许多方法。本文从三个角度出发,试图解释清楚新手面对 Python 虚拟环境时经常遇到的困惑。
- Python 虚拟环境是如何创建的
- 系统如何识别并套用某个虚拟环境
- Python 虚拟环境有哪些实现且推荐使用哪个虚拟环境管理器
1. 如何理解 Python 虚拟环境·
现阶段有若干个 Python 虚拟环境生命周期管理方法,这里列举较为常用的两种:
Python 虚拟环境(Isolated Environment)看似神秘,实则非常简单,它的存在依赖于两种 Linux 对象:
PATH环境变量- 独立的 Python 虚拟环境对应的目录
使用下列命令可以输出环境变量:
1 | echo $PATH | sed 's/:/\n/g' | sort |
查看不同虚拟环境下 PATH 环境变量的差异。
fuzzware 虚拟环境:
1 | /bin |
angr 虚拟环境:
1 | /bin |
可以明显发现, PATH 在 miniconda3 env 相关的行中,存在着与虚拟环境名相同的关键字。因此可得以下结论:Python 虚拟环境是在独立的文件夹里创建 Python 目录结构,执行虚拟环境切换时会将 PATH 中相关的字段替换为对应的虚拟环境路径。
下面是一个由 conda 创建的虚拟环境目录 layout,与 Linux 根目录布局很相似。
1 | . |
VSCode 在打开文件夹时,可以选择合适的 Python 虚拟环境。VSCode 有一套方法可以扫描系统安装的虚拟环境,但是我们之前说过,虚拟环境从存储上看就是一个文件夹,因此 VSCode 并不一定能扫描到全部的虚拟环境,必要时还得手动指定。不过使用 conda 一般没有问题。
2. 如何使用工具管理虚拟环境·
网上关于 conda 和 virtualenv 的对比已经有很详细的描述了,在此我们不再赘述。这里给出几个重要的观察:
virtualenv是一个 Python 虚拟环境管理工具,而conda不仅可以管理虚拟环境,还是一个高级的 Python 包管理器(与pip类似)。pip可以管理 Python 的第三方库,但是不会对第三方库中的 binary 做兼容性检查,而conda的检查更为严格。conda有自己的上游认证过的 Python 库,而且是二进制发行版,安装速度更快。conda尽管有无数优势,但是它的库并不全,有些冷门的 Python 库还是需要用pip安装,好在pip是装在虚拟环境的bin目录里,因此也可以在虚拟环境里使用用户态的pip(不加sudo)。
这里推荐不要安装 debian apt 仓库里的 Python,而是直接使用 conda 提供的 Python.
2.1 创建特定 Python 版本的虚拟环境·
使用 conda 命令创建 Python 3.6 版本的虚拟环境。
1 | conda create -n <ENV_NAME> python=3.6 |
2.2 列出当前安装的虚拟环境·
1 | conda env list |
2.3 将当前虚拟环境导出为 requirements.txt 文件·
将 ENV_NAME 环境中包含的所有 Python 库导出为 requirements.txt 文件:
1 | conda deactivate |
随后,可以使用如下命令重新安装所有的 Python 模块:
1 | conda install --file requirements.txt |
注意两点:
- 不要在
base环境里做任何安装,因为base环境在导出时会遇到一些麻烦。建议创建一个normal环境用来日常使用,无非就是在.zshrc里添加一行conda activate normal而已。 - conda 导出的包里有可能包含 pip 安装的一些、conda 上游仓库中不存在的包,下次安装时 conda 找不到这种包,会直接报错,建议根据错误信息做修改。
3. 硬核观察·
用 conda 创建虚拟环境有时会非常快,因为 conda 使用硬链接机制索引 Python 组件中的重复文件,避免了从网上下载相同版本 Python 组件带来的存储开销。我们通过下面两张图的对比可以看到,在移除 test 虚拟环境之后,文件 x86_64-conda-linux-gnu-ld 的 inode 索引计数减少 1. 因此在不要求特定 Python 版本而只要求环境隔离的情况下,可以肆无忌惮地创建 Python 虚拟环境。


总结·
通过深入理解 Python 虚拟环境的实现方式,有助于用户更容易地使用 conda 等工具创建自己的虚拟环境。通过导出虚拟环境,也可以实现良好的持久化存储。不过要注意,pip 和 conda 可以共存,比如在某个虚拟环境里安装一些 conda 仓库里不存在的包,就需要用 pip 安装。此时 pip 会将包安装在虚拟环境里,而非安装在系统目录里。这时候再导出、导入就会发生问题,因为 requirements.txt 里有些包 conda 装不上,pip 能装但是版本不一定合适。因此建议,不要混用 pip 和 conda,除非万不得已。





