Python 用virtualenv隔离项目依赖关系

Python 用virtualenv隔离项目依赖关系,Python有强大的打包系统,可用来管理程序的模块依赖关系。你可能已经用pip打包管理命令安装过第三方软件包。

使用pip安装有一个问题,那就是软件包默认会被安装到全局Python环境中。

当然,这样安装的新软件包能在系统上随意使用。但如果正在处理多个项目,每个项目需要同一个软件包的不同版本,那么很快就会导致一场噩梦。例如,一个项目需要库的1.3版本,而另一个项目需要这个库的1.4版本。

在全局安装软件包时,所有程序只能使用同一版本的Python软件包,因此会遇到版本冲突问题,就像电影Highlander一样。

还可能更糟,不同的程序可能会用到不同版本的Python。例如,有些程序仍然在Python 2上运行,而大部分新程序都是在Python 3中开发的;或者某个项目需要Python 3.3,而其他所有项目都在Python 3.6上运行。
除此之外,全局安装Python软件包也会带来安全风险。修改全局环境通常需要用超级用户(root/admin)权限运行pip install命令。由于pip在安装新软件包时是从互联网下载代码并执行,因此通常不建议用超级用户执行。虽然大家都希望代码是值得信赖的,但是谁知道它会真正做些什么?

Python 用virtualenv隔离项目依赖关系 使用虚拟环境

解决这些问题的办法是使用所谓的虚拟环境将各个Python环境分开,即按项目隔离Python依赖,每个项目能选择不同版本的Python解释器。
虚拟环境是一个隔离的Python环境。从物理上来说,虚拟环境位于一个文件夹中,其中含有所需的软件包和依赖,比如Python项目需要用到的本地代码库和解释器运行时。(实际上可能没有完全复制这些文件,只是使用了占用硬盘空间较少的符号链接。)
为了演示虚拟环境的工作方式,下面快速走一遍流程来设置一个新的环境(简称为virtualenv),在其中安装第三方软件包。
首先来查看全局Python环境所在的位置。在Linux或macOS上,使用which命令行工具查找pip程序包管理器的路径:

$ which pip3
/usr/local/bin/pip3

我通常将虚拟环境直接放入项目文件夹中,以便更好地组织项目和分离环境。你可以自行决定,比如在专门的python-environments目录下保存所有项目的环境。
下面来创建一个新的Python虚拟环境:

$ python3 -m venv ./venv

执行这条命令会花一点时间,然后在当前目录中创建一个新的venv文件夹,其中含有基本的Python 3环境:

$ ls venv/
bin        include      lib        pyvenv.cfg

如果使用which命令检查当前的pip版本,会发现仍然指向全局环境,在这里是/usr/local/bin/pip3:

$ which pip3
/usr/local/bin/pip3

这意味着如果现在安装软件包,仍然是安装到全局Python环境中。因此创建一个虚拟环境文件夹还不够,用户需要显式激活新的虚拟环境,这样才会运行其中的pip命令:

$ source ./venv/bin/activate
(venv) $

运行activate命令将会让当前的shell会话使用虚拟环境中的Python和pip命令。2
2在Windows上直接运行activate命令,不用加前缀。

注意,这会改变shell提示符,将激活的虚拟环境的名称包含在圆括号中:(venv)。现在再来看看当前使用的是哪个pip可执行文件:

(venv) $ which pip3 /Users/dan/my-
project/venv/bin/pip3

从中可以看到,运行pip3命令不再执行全局环境中的程序,而是执行虚拟环境中的pip。Python解释器可执行文件也是如此,现在从命令行运行python也会从venv文件夹加载解释器:

(venv) $ which python /Users/dan/my-
project/venv/bin/python

注意,现在仍然是一个空白且完全干净的Python环境。运行pip list显示的已安装软件包列表只有寥寥几项,仅包含pip本身所需的基本模块:

(venv) $ pip list
pip (9.0.1)
setuptools (28.8.0)

现在继续在虚拟环境中安装一个Python软件包,此时需要用到熟悉的pip install命令:

(venv) $ pip install schedule
Collecting schedule
  Downloading schedule-0.4.2-py2.py3-none-any.whl
Installing collected packages: schedule
Successfully installed schedule-0.4.2

注意到这里有两个重要的变化:首先,运行pip命令不再需要管理员权限;其次,在当前虚拟环境中安装或更新软件包意味着这些文件最终都位于虚拟环境目录的子文件夹中。
因此,这个项目的依赖关系与系统上其他所有Python环境(包括全局的Python)在物理上都是分离的。实际上现在获得了专门用于这个项目的Python运行时副本。
再次运行pip list,会看到schedule库已成功安装到新环境中:

(venv) $ pip list
pip (9.0.1)
schedule (0.4.2)
setuptools (28.8.0)

只要这个环境在当前shell会话中一直处于激活状态,那么使用python命令或执行独立的.py文件,都会使用虚拟环境中安装的Python解释器和依赖项。
但如何停止或“离开”虚拟环境呢?与activate命令类似,还有一个deactivate命令可以回到全局环境:

(venv) deactivate which pip3
/usr/local/bin

使用虚拟环境既有助于保持系统整洁,又能理清Python依赖关系。虚拟环境是一种最佳实践,所有Python项目都应该使用它来分离各自的依赖关系和避免版本冲突。
理解和使用虚拟环境之后,就能进一步使用更高级的依赖关系管理方法,如用requirements.txt文件指定项目依赖关系。
如果想深入探讨这个主题,了解更多的高效技巧,那么请务必查看dbader.org上的“管理Python依赖关系”(Managing Python Dependencies)课程。

关键要点

  • 虚拟环境用来隔离项目依赖,既能帮助避免软件包的版本冲突,又能使用不同版本的Python运行时。

  • 虚拟环境是一种最佳实践,所有Python项目都应使用它来存储依赖关系。这样能免去很多麻烦。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程