在前面几篇博客中我们介绍过docker等容器的编程环境解决方案,但是容器作为一个系统级的隔离方案,其实更加强调的是用户间的隔离,这一点也得益其对NameSpace技术的推广和使用。但是在一部分的场景下,比如快速构造一个纯净的python环境、轻量级的操作实现不同python包的共存,容器技术虽然也可以完成,但是功能显得过于冗余,这就需要使用到本文所介绍的virtualenv这样的一个python依赖管理解决方案。文中我们介绍了virtualenv的安装与基本的使用方法,做了一遍比较完整的演示。

技术背景

在前面几篇博客中我们介绍了容器的使用(​​博客1​​​、​​博客2​​​、​​博客3​​​、​​博客4​​​、​​博客5​​​),容器是一种系统级的隔离方案,更多的强调资源上的隔离。而这里我们要介绍的python的虚拟环境,更加强调的是依赖的管理。假如一个python项目需要依赖于​​numpy==1.20.1​​​的版本,另一个python项目必须依赖于​​numpy==1.20.2​​​的版本。虽然我们也可以直接使用docker或者其他的容器方案来隔离编程环境,但是这会消耗比较大的资源,因为我们并不需要重新构造一整个系统。因此python也提供了一种更加优雅的解决方案:使用​​virtualenv​​​来构造一个虚拟的python库的环境,这里面我们可以定制化自己所需的python依赖的版本。比较详细的virtualenv使用方法可以参考​​官方文档​​,这里我们仅做一些简单的使用方法的介绍和演示。

安装virtualenv

virtualenv可以直接通过pip来安装和管理,这也大大简化了我们的操作:

[dechin@dechin-manjaro virtualenv]$ python3 -m pip install virtualenv
Collecting virtualenv
Downloading virtualenv-20.4.3-py2.py3-none-any.whl (7.2 MB)
|████████████████████████████████| 7.2 MB 7.5 MB/s
Requirement already satisfied: appdirs<2,>=1.4.3 in /home/dechin/anaconda3/lib/python3.8/site-packages (from virtualenv) (1.4.4)
Collecting distlib<1,>=0.3.1
Downloading distlib-0.3.1-py2.py3-none-any.whl (335 kB)
|████████████████████████████████| 335 kB 8.5 MB/s
Requirement already satisfied: filelock<4,>=3.0.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from virtualenv) (3.0.12)
Requirement already satisfied: six<2,>=1.9.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from virtualenv) (1.15.0)
Installing collected packages: distlib, virtualenv
Successfully installed distlib-0.3.1 virtualenv-20.4.3

需要注意的是,这里虽然我们可以通过virtualenv来构造一个纯净的python编程环境,但是python的版本是直接依赖于系统里面所包含的python版本的,我们不能通过virtualenv去构造一个不同的python版本。

virtualenv的使用

virtualenv的使用步骤基本上可以简单划分为:创建环境-激活环境-配置和使用环境-关闭环境,以下分别进行演示。

创建一个虚拟环境

首先我们进入到一个空的目录:

[dechin@dechin-manjaro virtualenv]$ ll
总用量 0

然后直接执行​​virtualenv envname​​​的命令来构建一个虚拟环境,这里因为我们系统中只有一个python版本,多个python版本的环境需要使用​​-p​​选项来进行配置。

[dechin@dechin-manjaro virtualenv]$ virtualenv test_env
created virtual environment CPython3.8.5.final.0-64 in 295ms
creator CPython3Posix(dest=/home/dechin/projects/2021-python/virtualenv/test_env, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/dechin/.local/share/virtualenv)
added seed packages: pip==21.0.1, setuptools==54.1.2, wheel==0.36.2
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

执行完成上述指令之后,我们发现在刚才的目录下生成了一个与虚拟环境名称一致的目录名:

[dechin@dechin-manjaro virtualenv]$ ll
总用量 4
drwxr-xr-x 4 dechin dechin 4096 41 21:06 test_env

这就代表虚拟环境已经创建成功了。

激活虚拟环境

在使用一个指定的虚拟环境时,我们需要先激活这个虚拟环境,在虚拟环境目录下的bin目录中,有一个名为activate的可执行文件,就是用来激活虚拟环境的:

[dechin@dechin-manjaro virtualenv]$ source test_env/bin/activate
(test_env)[dechin@dechin-20n2s01200 virtualenv]$ python3 -m pip list
Package Version
---------- -------
pip 21.0.1
setuptools 54.1.2
wheel 0.36.2

我们可以发现一个特点,在激活虚拟环境后,在Linux的命令行之前都会带有一个虚拟环境的名称,用于区分当前所在的虚拟环境。而这里虚拟环境中的python第三方库是几乎没有的,是一个非常纯净的环境,需要我们自己去手动安装与配置环境。

安装与配置python库

在虚拟环境中的操作跟在实际环境中的安装操作是一致的,我们一样也可以使用pip来进行安装包的管理,只是这时候安装所执行的变更只会保存到当前的虚拟环境下,不影响实际环境和其他的虚拟环境。

(test_env)[dechin@dechin-manjaro virtualenv]$ python3 -m pip install numpy
Collecting numpy
Downloading numpy-1.20.2-cp38-cp38-manylinux2010_x86_64.whl (15.4 MB)
|████████████████████████████████| 15.4 MB 295 kB/s
Installing collected packages: numpy
Successfully installed numpy-1.20.2
(test_env)[dechin@dechin-manjaro virtualenv]$ python3 -m pip list
Package Version
---------- -------
numpy 1.20.2
pip 21.0.1
setuptools 54.1.2
wheel 0.36.2

安装完成后,我们看到当前安装的numpy版本号是1.20.2。让我们再打开一个新的终端窗口看下实际环境中的numpy的版本号:

[dechin@dechin-manjaro virtualenv]$ python3 -m pip show numpy
Name: numpy
Version: 1.20.1
Summary: NumPy is the fundamental package for array computing with Python.
Home-page: https://www.numpy.org
Author: Travis E. Oliphant et al.
Author-email: None
License: BSD
Location: /home/dechin/anaconda3/lib/python3.8/site-packages
Requires:
Required-by: xarray, vaex-core, tifffile, tables, statsmodels, seaborn, scipy, scikit-learn, scikit-image, PyWavelets, pytools, pythreejs, pyscf, pyarrow, projectq, plotdigitizer, patsy, pandas, opencv-python, numexpr, numba, mkl-random, mkl-fft, matplotlib, ipyvolume, ipydatawidgets, imageio, hiq-projectq, h5py, cupy, bqplot, Bottleneck, bokeh, bkcharts, astropy, ts, hiqfermion

这里可以区分的是,实际环境中命令行的前面不带有虚拟环境的名称。我们可以看到实际环境下的numpy版本是1.20.1,这样一来我们就用这么一个开销并不是很高的方式,实现了两个不同的numpy版本的共存。

退出虚拟环境

在当前的虚拟环境下,可以直接执行​​deactivate​​退出。我们可以测试这样的一个场景:先退出虚拟环境,然后再次进入,以确认刚才的操作被自动的保存到了虚拟环境中:

(test_env)[dechin@dechin-manjaro virtualenv]$ deactivate
[dechin@dechin-manjaro virtualenv]$ source test_env/bin/activate
(test_env)[dechin@dechin-manjaro virtualenv]$ python3 -m pip list
Package Version
---------- -------
numpy 1.20.2
pip 21.0.1
setuptools 54.1.2
wheel 0.36.2
(test_env)[dechin@dechin-manjaro virtualenv]$ deactivate

在上述的执行结果中可以看到,对python环境的变更是永久保存下来了的。这一点上来说操作也比docker容器更加容易,在docker中如果需要持久化的保存一个操作,需要在对容器镜像操作之后,执行额外的commit指令才能保存。因此我们认为virtualenv是一个更加优雅、更加轻量级的,python环境差异化管理的解决方案。

总结概要

在前面几篇博客中我们介绍过docker等容器的编程环境解决方案,但是容器作为一个系统级的隔离方案,其实更加强调的是用户间的隔离,这一点也得益其对NameSpace技术的推广和使用。但是在一部分的场景下,比如快速构造一个纯净的python环境、轻量级的操作实现不同python包的共存,容器技术虽然也可以完成,但是功能显得过于冗余,这就需要使用到本文所介绍的virtualenv这样的一个python依赖管理解决方案。文中我们介绍了virtualenv的安装与基本的使用方法,做了一遍比较完整的演示。

版权声明


作者ID:DechinPhy