Python 虚拟环境管理——venv
之前主要使用的都是conda的虚拟环境,图的是方便省事,但是始终无法理解虚拟环境的底层逻辑, 这里选择学习最简单的、也是python基础的venv虚拟环境。
venv 虚拟环境是Python提供的一个工具,用于创建隔离的环境来管理不同项目的依赖关系,每一个虚拟环境实际存储于一个目录下, 但是可以在任何其它位置激活和使用这个虚拟环境。
在Linux中即使有 Python,也可能不包括 venv,需要额外下载 python3-venv 。
创建虚拟环境
在当前目录下创建一个名为 myenv
的虚拟环境(但是按照惯例,虚拟环境的名称通常为venv
或.venv
)
1
python -m venv myenv
这实际会在当前目录下创建一组文件和子目录,通常包括以下几个关键部分:
bin/
(或Scripts/
):包含一组独立的Python解释器(可执行文件)和工具(如pip);lib/pythonX.Y/site-packages/
(或lib/site-packages/
):存放该虚拟环境下所有的Python库,初始情况下只有pip。include/
:包含C语言头文件,用于在该虚拟环境中进行C扩展编译。pyvenv.cfg
:包含虚拟环境的配置信息(如Python版本信息,创建时的命令)。
这些目录结构对于Windows和Linux存在一些细微区别,涉及的命令脚本实际上也提供了bash,cmd和pwsh这几个版本,下面的讨论主要以Windows为例。
pyvenv.cfg
大致包括如下内容: 1
2
3
4
5home = D:\ProgramLang\miniconda3
include-system-site-packages = false
version = 3.12.1
executable = D:\ProgramLang\miniconda3\python.exe
command = D:\ProgramLang\miniconda3\python.exe -m venv D:\ProjectRoot\Test\TestPyPi\myenv
由于虚拟环境中可能存在很多信息是和绝对路径相关的(例如上面的
pyvenv.cfg
),所以最好不要直接将myenv/
文件夹整体复制到其它地方进行使用,可能存在潜在的问题。
激活、退出虚拟环境
激活(当前目录下的)虚拟环境 1
2
3
4
5# windows
.\myenv\Scripts\activate
# linux
source myenv/bin/activate
当然在其它目录下的虚拟环境也可以被激活和使用,只需要相应调整命令中的路径。
激活环境之后,shell的命令行提示符通常会变化,自动提示当前虚拟环境的名称,例如
1
(myenv) user@xxx$
使用deactivate命令可以退出当前的虚拟环境 1
deactivate
激活虚拟环境实际上就是调用了对应目录中的激活脚本,执行了一些简单操作,主要包括:
- 修改环境变量
PATH
,将当前目录添加到环境遍历路径的开头,确保python
,pip
等命令会优先找到当前虚拟环境中的实例; - 将当前环境的
site-packages/
目录添加到模块搜索路径中,确保可以成功导入当前环境中所安装的包; - 提供一个
deactivate
命令,作用就是将activate
所做的修改撤销。
可以通过设置环境变量VIRTUAL_ENV_DISABLE_PROMPT
来关闭虚拟环境对提示符的修改,例如
1
$Env:VIRTUAL_ENV_DISABLE_PROMPT = "true"
如果需要删除虚拟环境,只需要删除对应的目录即可。
这里的激活/退出虚拟环境操作都和conda有所不同,例如conda的退出命令是完整的conda deactivate
。
在虚拟环境中安装python包
在激活虚拟环境之后,可以使用pip安装依赖: 1
pip install <package_name>
注意:不激活虚拟环境时直接调用的pip是全局的,激活环境后调用的pip则是虚拟环境中的,激活与否会影响python包的实际安装位置。
例如默认情况下,site-packages/
目录的内容如下:
1 | site-packages/ |
这里需要解释一下,pip本质上仍然是一个Python包,Scripts
目录中的
pip.exe
只提供一个入口功能,实际还会调用site-packages/pip/
目录中的内容。
pip-23.2.1.dist-info
目录用于存储与安装的 pip
包版本相关的元数据。
我们可以手动安装一个包,例如tqdm
1
pip install tqdm
这个命令会自动下载两个包:colorama
,
tqdm
,前者是tqdm的必要依赖。
此时虚拟环境中发生了一些变化,site-packages/
目录中增加了对应的目录:
1 | site-packages/ |
由于tqdm
还提供了一个可执行文件,因此Scripts/
目录中还添加了一个tqdm.exe
,可以在命令行中直接调用。
导出依赖与恢复
我们可以导出当前虚拟环境的所有依赖,并保存到文件中,方便下次安装
1
pip freeze > requirements.txt
可以在其它位置通过该 requirements.txt
文件安装所有的依赖,从而恢复相同的虚拟环境 1
pip install -r requirements.txt
补充
除了通过 PyPi 进行安装之外,pip 还支持很多安装方式,主要包括:
- 通过 Github
仓库安装:
pip install git+https://github.com/user/repo.git
;(要求该仓库的内容符合 Python 包的格式标准,例如有setup.py
文件等) - 通过 .tar.gz 或 .zip
文件进行源码安装:
pip install /path/to/package.tar.gz
;(支持直接使用网络上的压缩包)(要求这些压缩包中的内容符合 Python 包的格式标准) - 使用 Python 设计的 wheel 文件(后缀
.whl
)进行模块的安装,wheel 文件是被设计替代源码压缩包的二进制文件,它相比于压缩包的优势是已经包含了所有编译好的二进制文件,因此安装速度更快,并且可以避免一些编译问题。
pip 自身可能会尝试处理一些包之间的依赖关系,自动获取缺失的依赖,但是对于一些复杂的依赖关系,可能会出现一些问题,例如依赖的版本问题。 conda 也是一样的,它会自动管理各个包之间的依赖关系,在 conda 环境中混合使用 pip 进行安装时,更可能会产生一些冲突问题。
pip + venv 相比于 conda 有一些明显的优缺点:
- 优势:pip 和 venv 的使用都比 conda 更加简单轻量级,conda环境还是太重了;
- 缺点:venv 只能基于当前系统安装的 Python 版本来创建虚拟环境,不能切换 Python 版本;pip 只能管理 Python 包,不能管理其他语言的包。