Python有着众多的第三方库,这些库版本和库的依赖库版本可能会有着非常复杂的关系,这给我们开发时的依赖管理带来了难度。Python中如果不考虑虚拟环境,我们只能全局安装一个特定版本的库(这和Java的Maven仓库集中支持多版本的库不同),而我们不同的工程可能要依赖不同版本的依赖库,难道我们切换工程还要同时装卸一组不同的库吗?
在Python生态中,这个问题是通过创建虚拟环境解决的。我们创建一个新工程时,可以使用Python内置的venv
工具为该工程创建Python虚拟环境,这个虚拟环境会复制全局安装的Python中的重要文件,该工程使用的python
、pip
命令以及site-packages
目录都是由这个虚拟环境提供的,而非来自于全局安装的Python,我们针对该工程安装、卸载扩展库也都是针对这个虚拟环境来操作,而不会影响到全局。
通过以下命令,在当前环境下创建一个虚拟环境。
python -m venv ./venv/
执行这条命令后稍等一会,就能在当前目录下的venv
文件夹内自动生成虚拟环境所需的文件了,然后我们运行venv/Scripts/activate.bat
(Windows CMD)或是venv/Scripts/activate
(Linux),我们当前的虚拟终端内就会切换到虚拟环境,此时再使用python
、pip
等命令都是针对虚拟环境来操作的。
不过这里要注意,实际上venv
的原理就是文件复制,因此假如我们的Python版本为3.10
,我们也只能创建3.10
的虚拟环境。假如我们一定要创建其它版本的虚拟环境,venv
没有这样的功能,我们只能再全局安装对应版本的Python然后用对应版本下的venv
来创建虚拟环境。如果确实需要多版本的Python管理,你可能需要使用conda
。
在其他开发语言环境中,例如使用Maven
或是npm
之类的包管理工具时,我们的工程都必须有一个依赖描述文件,但Python中对依赖库的管理比较松散,如果不使用venv
,依赖全部是全局安装,依赖管理也是比较难做到的,因此这个依赖描述文件也不是强制性的。但使用venv
时,还是推荐更加规范的做法。我们可以执行以下命令导出当前虚拟环境中安装的所有扩展:
pip freeze > requirements.txt
该命令首先调用pip freeze
,将venv
环境中的全部依赖导出,下面是一个例子输出。
click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
Werkzeug==1.0.1
然后我们将生成的内容重定向到了requirements.txt
文件中。根据这个文件,我们在一个新的venv
环境下也能快速安装该工程的所有依赖了。
pip install -r requirements.txt
注:我们可以看到,requirements.txt
这个文件名其实是我们自己起的,Python并没有强制要求叫这个名字,但这是一种约定,推荐使用。
virtualenv:Python中的venv
实际上是在Python3.3版本引入的,它的设计灵感来源于virtualenv
工具。virtualenv
是一直以来都广泛使用的Python虚拟环境创建工具,它的基础使用方式和venv
类似,但virtualenv
支持更多的选项和参数,能够更精细的控制我们创建的Python虚拟环境,virtualenv
相比venv
唯一的劣势就是它不是Python内置的工具,实际上我们使用任何一个皆可。
conda:conda
也可以用于创建Python虚拟环境,conda
主要应用于科学计算、机器学习等领域,除了创建虚拟环境还可以用于Python版本管理、包管理等用途,旨在为不懂软件工程的人员提供“傻瓜”式的Python一键安装环境。在科学计算、机器学习领域推荐使用conda
,其它方向则不推荐。