使用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  4月  1 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: //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的安装与基本的使用方法,做了一遍比较完整的演示。

版权声明

本文首发链接为://www.cnblogs.com/dechinphy/p/virtualenv.html
作者ID:DechinPhy
更多原著文章请参考://www.cnblogs.com/dechinphy/