建议在开发环境和生产环境下都使用虚拟环境来管理项目的依赖。 - Flask

背景

Python 应用通常会使用一些第三方的软件包和模块。不同的应用可能会依赖不同版本的同一个软件包,或者依赖不同的 Python 版本。

设想这样的场景:

小白之前有一个 Flask 0.10 做的网站并且一直维护着。现在老板要求在同一个机器上使用最新版的 Flask 1.1 再做一个网站,两个网站以后都要用。这样,在机器上安装 Flask 0.10 或者 Flask 1.1 都会导致某一个网站无法运行。

为了解决类似这样的问题,虚拟环境上场了。

究竟什么是虚拟环境

每个虚拟环境都是一个独立于操作系统和其他虚拟环境的,被隔离的(isolated), Python 环境。

它拥有自己的 Python 二进制文件,并且拥有独立的已安装软件包集(site-package)。

正是因为每个虚拟环境的 Python 和 site-package 都是独立的,我们只要为每个项目配置自己的虚拟环境,然后就可以在项目各自的环境中安装各自依赖的软件包,而不用担心这些软件包和其他项目是否冲突了。

如何配置虚拟环境

开始配置之前,我们需要选择一个配置环境的工具包。

选择工具包

Python 配置虚拟环境的包有很多,最受好评的莫过于 virtualenv,甚至从 Python 3.3 开始,virtualenv 的一个功能子集被集成到了 Python 标准库的 venv 模块中。

virtualenv 和 venv 都是很好的选择,二者各有优劣。

virtualenv

venv

优势

1. 控制版本,可以将虚拟环境配置成不同于系统 Python 版本的其他版本

2. 创建 bootstrap 插件

3. 可重定位

4. Python 3.3 之前版本的首选

1. Python 3.3 以后内置于标准库

2. 浓缩了 virtualenv 的精华

劣势

1. 属于第三方库,使用前需要在系统中 pip install virtualenv

2. 功能冗余,小型项目用不太到很多功能

1. 不能将虚拟环境配置成不同于系统 Python 版本的其他版本

2. Python 3.3 之前版本无法使用

建议是,小型且对 Python 版本无特殊需求的项目,venv 足够了,其他情况用 virtualenv。

使用方法

venv

下为 linux/MacOS 示例,Windows 仅个别目录或文件名不同,原理一致,具体可参考官方文档。

假设项目的根目录为 /home/username/application/

进入项目根目录

$ cd /home/username/application/

复制代码创建虚拟环境

$ python3 -m venv 虚拟环境名

复制代码

例如,

$ python3 -m venv test-env

复制代码

这样在根目录中会出现一个 test-env 的目录,如下

application/
/test-env/
/bin/
/include/
/lib/
/share/
/lib64
/pyvenv.cfg

复制代码

这个 test-env 目录就是新创建的虚拟环境了。

进入虚拟环境

运行刚创建的虚拟环境目录中 /bin 中的 activate 即可

$ source /path/to/虚拟环境名/bin/activate

复制代码

$ source test-env/bin/activate

复制代码

$ . test-env/bin/activate

复制代码

这时,你会发现 Terminal 提示符多了个前缀 (test-env),括号中的内容代表当前的虚拟环境

(test-env) $

复制代码

可以通过 pip list 列出所有安装的软件包,会发现只有这俩

$ pip list
pip (9.0.1)
setuptools (39.0.1)

复制代码

当前状态下,cd 不会改变虚拟环境的状态,哪怕是出了项目根目录。

在虚拟环境中,就可以肆无忌惮的 pip install 了。

退出虚拟环境

输入 deactivate (或关闭 Terminal) 即可。这时再输入 pip list 又会显示系统环境所有安装的软件包了,而且提示符前面的 (test-env) 也没了。

(test-env) $ deactivate
$ pip list
Package Version
--------------------- -------------------
apturl 0.5.2
asn1crypto 0.24.0
Brlapi 0.6.6
certifi 2019.9.11
...

复制代码删除虚拟环境

只需将之前创建的 test-env 目录整体删掉就好了。

注意,删除虚拟环境会连同之前在虚拟环境中安装的所有软件包一起删除。

$ rm -r /path/to/虚拟环境名

复制代码

virtualenv

与 venv 大同小异,具体可参考官方文档。

假设项目的根目录为 /home/username/application/

安装

$ pip install virtualenv

复制代码进入项目根目录

$ cd /home/username/application/

复制代码创建虚拟环境

$ virtualenv 虚拟环境名

复制代码进入虚拟环境

$ source /path/to/虚拟环境名/bin/activate

复制代码退出虚拟环境

$ deactivate

复制代码删除虚拟环境

$ rm -r /path/to/虚拟环境名

复制代码

说个 Bug

如果你的系统是 Ubuntu ,那么,在虚拟环境中使用 pip list 或 pip freeze 时,会多处一项 pkg-resources (0.0.0) 或 pkg-resources==0.0.0。

看似是个不起眼的小 bug,但是,当用 pip freeze > requirements.txt 生成当前项目依赖时,如果不将 pkg-resources==0.0.0 这条删除,在下次使用 pip install -r requirements.txt 时,就会报错说找不到 pkg-resources==0.0.0 啥啥啥的。别问我是怎么知道这个细节的。。