⚠警告
受限于笔者的知识储备与开发经验,文章中难免会出现错误或异想天开等不符合实际情况的暴论,请您谨慎甄别取用。如您发现错误结论或其他需要修改的问题,可发送电子邮件至 well_404@outlook.com 以联系笔者进行更正。
文章开始前,那么聪明的你可能会有所疑问:“为什么要学多份虚拟环境管理工具?”实际上本文介绍的三者均是成熟的虚拟环境管理工具,并且都可以相互独立运行,但相对的各有各的专场以及不足。在文章中,我们将简要分析其基本用法以及其适应的领域,以帮助你在实际的开发中找到合适的虚拟化方案。
conda
Package, dependency and environment management for any language—Python, R, Ruby, Lua, Scala, Java, JavaScript, C/ C++, FORTRAN
conda 相对于主流的虚拟环境管理工具,在 python 开发环境中最大的特点便是 “不需要安装python”。但请不要误会,这并不意味着 conda 不需要 python 来运行脚本,而是 conda 不会依赖于系统中已经存在的 python 进行运行。因此 conda 拥有较高的独立性以及强悍的跨版本支持,在多版本管理上,目前仍未出现能够击溃 conda 的存在。
但与此同时,conda 对于虚拟环境的管理便显得非常“力大砖飞”,这也同样归功于其强大的跨版本支持上,通过 conda 可以轻松的在创建虚拟环境时仅需一个参数使用任意一个 python 版本,即便系统中不包含该版本的 python。但与之而来的便是其虚拟环境的实现方式极其暴力,每个虚拟环境中均包含了一个完整的 python,即便是在统一系统中已经有了该版本的 python 解释器也会创建一个新的解释器专供该环境使用。因此,conda 的虚拟环境实际上与主流的虚拟环境存在天壤之别。这也带来了 conda 最大的缺点之一——极度浪费磁盘空间。
本质上,conda 的虚拟环境更像是对整个开发环境的虚拟,而不是 poetry 和 pdm 那种在解释器层面的虚拟,这是它原生支持多种编程语言的原因,也是一些科学计算、深度学习项目唯一指定的开发环境的原因。
也正因如此,conda 相较于其他虚拟环境的管理器来说,其上手难度也相对更低一些,仅需要学会 创建环境、进入环境、退出环境、删除环境 即可轻松使用 conda 了,也就是四条指令的难度,因此对于刚入门的开发者来说,conda 相对于其他传统的虚拟环境也更加容易入门。
因此,对于 conda 的使用,笔者个人看法是建议普通用户中 不理解传统虚拟环境使用方法的新手 以及 多版本开发者 进行使用,当然对于科学计算方面的开发者并没得选,而对于单版本多环境的开发者来说,poetry 或 pdm 是你更好的选择。
conda的优势:简单易学、跨版本、独立性、兼容性极高、科学计算指定环境
conda的劣势:体积大、复用度低、实现原理“力大砖飞”
安装conda
在版本选择方面,conda 提供了两种工具可供选择:anaconda 与 miniconda。
关于二者的选择,可以参考官方的描述。
anaconda 内置了大量的额外内容,例如大量科学计算、深度学习及数据分析相关的库。也正因如此其官方的推荐硬盘空间是3GB及以上,对于非相关领域的工笔者来说将会付出巨大的空间成本。因此我们将使用的工具实际上是 miniconda,而不是 anaconda。
miniconda 相对于 anaconda 仅保留了虚拟环境相关的功能而去除了大量无关的内容,因此体积更小,官方推荐硬盘空间是500MB及以上,内容仅包含 conda、python、一些依赖以及较为常用的python第三方库例如 pip、zlib 等。
miniconda 由于较为精简,相对于 anaconda 去掉了图形化的管理界面,因此对于“命令行恐惧症患者”来说也可以选择 anaconda 进行图形化操作。不过 conda 的使用方法极为简单,且 anaconda 的GUI界面实际上并不好用且非常卡(可能是用 Python 的UI库写的吧),笔者仍然建议使用 miniconda 与命令行工具进行操作。anaconda 与 miniconda 的命令行操作一致,在此将不会分别进行演示。
conda 官方文档:https://docs.conda.io/projects/conda/en/latest/index.html
Anaconda 官方网站:https://www.anaconda.com/
Anaconda 下载地址:https://www.anaconda.com/products/distribution#Downloads
miniconda 下载地址:https://docs.conda.io/en/latest/miniconda.html
一般来说,较新的 conda 的 python 版本仅会影响 base 的环境,对于虚拟环境的使用差别并不大,因此我们仅需要下载对应的最新版并安装即可。
Windows
在 miniconda下载地址 中选择合适的版本进行下载。64位用户可以直接点击这里下载最新版的安装包进行安装。
由于 Windows 下的 miniconda 安装并无什么难度,基本上一路 next 就可以了,在此不进行演示。
千万不要将 miniconda 安装到任意一个Program Files路径下,此操作将会导致 conda 因权限问题无法使用
注意在安装前最后一步将 miniconda 添加至环境变量。
注意这四个选项一定要全部勾选!这里也推荐勾选第二项以方便在其他程序和终端中进行调用。
Linux(Ubuntu Server 20.04.4)
首先在官网选择合适的版本,并进行下载,然后运行下载好的安装脚本。
1 | wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh |
然后,系统会弹出使用协议之类的东西,一直按回车键(或按Q跳过)直到显示 Please answer 'yes' or 'no':'
并输入 yes
同意协议。此时系统会询问安装路径,一般情况下会安装在当前用户 home directory
的 miniconda
文件夹中,也就是 /home/username/miniconda
。
1 | Miniconda3 will now be installed into this location: |
一般情况下我们安装在此处即可,按回车键确认。此时便会开始安装,经过一小段时间的等待之后,我们便可以选择初始化 miniconda 了。
1 | Do you wish the installer to initialize Miniconda3 |
输入 yes
后便完成了安装。不过此时 miniconda 并不在系统变量中,无法直接通过命令调用,体现为:
1 | well404@ubuntu2004:~$ conda |
此时查看该用户的 .bsahrc
文件(cat ~/.bashrc
),我们可以看到其文件结尾处被添加了如下内容:
1 | # >>> conda initialize >>> |
此时,我们只需要重新加载 .bsahrc
或 重启终端 即可正常的导入环境变量了。输入 source ~/.bashrc
:
1 | well404@ubuntu2004:~$ source ~/.bashrc |
此时我们注意到我们的用户名前多了一个 (base)
,这便是 conda 激活了 base
环境(默认环境),此时查询版本信息等就是 miniconda 自带的 python 信息了。
1 | (base) well404@ubuntu2004:~$ python --version |
conda的基础使用
我们来简单介绍一些基础的使用方法,更多指令与操作可以查询官方文档。
使用conda创建虚拟环境
创建一个名为 test
的虚拟环境。
1 | conda create -n test |
创建一个名为 test
,且python版本为 3.8
的虚拟环境的虚拟环境。
1 | conda create -n test python=3.8 |
从已有的虚拟环境 test
复制一份为 test_copy
。
1 | conda create -n test_copy --clone test |
使用conda移除虚拟环境
移除一个名为 test
的虚拟环境。
1 | conda remove -n test --all |
查看conda虚拟环境列表
1 | conda env list |
使用conda激活虚拟环境
激活一个名为 test
的虚拟环境。
1 | conda activate test |
如果激活成功,在用户名前会有环境名的提示,例如:
1 | C:\Users\Well404>conda activate sign |
值得注意的是,Windows PowerShell 默认情况下无法直接激活 conda 虚拟环境,请务必在 Windows 系统中使用 cmd 进行操作或在 PowerShell 中使用 conda init
命令来初始化 conda 的配置。
退出conda虚拟环境
1 | conda deactivate |
值得注意的是,此命令不包含任何额外的参数。因为一个终端仅能同时激活一个虚拟环境,因此也没有必要指定取消激活的虚拟环境的环境名。
conda环境内的使用
由于使用了一个虚拟环境,在这个虚拟环境激活时,我们可以正常的使用 Python 中的绝大部分命令与工具,同时 conda 也提供了一些指令,但在此就不过多阐述了。
对于仅使用虚拟环境这一项功能的用户,我们可以直接使用正常操作 Python 的方式进行操作,例如使用 pip
安装第三方库,使用此环境下中 python 的命令行工具以及交互式编程等等,简而言之就是平时怎么用还怎么用,只要你的虚拟环境是激活的的状态,此环境内的改变是不会影响到其他无关的环境的。
poetry
作为一个传统虚拟环境的实现,poetry 凭借其强大的依赖分析能力被大量项目所推荐的虚拟环境管理工具。
对于绝大部分的开发者而言,poetry 作为首选的虚拟环境管理工具是最优方案,其强大的依赖分析能力、环境封装能力以及庞大的社区均可为你的开发保驾护航,这也是我目前最为推荐所有 python 开发者所掌握的虚拟环境管理工具。
poetry官方文档:https://python-poetry.org/docs/
poetry项目仓库:https://github.com/python-poetry/poetry
对于 poetry 的使用,笔者个人看法是建议 所有开发者 进行使用,其强大的性能足够满足绝大部分情况的需求(除非你还在使用远古版本的 python)。
poetry的优势:分析能力极强、社区资源丰富、兼容性优秀、使用广泛
poetry的劣势:对老旧版本的python不兼容、略微复杂
安装poetry
注意:poetry 仅支持 Python2.7 或 Python3.5+ 的版本,如果版本低于此请考虑升级 python 版本或使用其他虚拟环境管理工具(例如 conda)。
使用一键安装命令
osx / linux / bashonwindows
1 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - |
windows powershell
1 | (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python - |
手动拉取脚本进行安装
在 poetry 的 github 仓库中获取安装脚本后,使用 python 运行。
使用pip安装(不推荐)
我们也可以使用 pip 安装 poetry,但这仅在一个空白的环境中是较为合适的,例如用 conda 创建的新环境或新安装的 python,直接使用 pip 安装可能会造成依赖冲突。
1 | pip install poetry |
添加poetry至环境变量
安装完成后,可以尝试使用 poetry --version
来确认其是否安装成功并添加至环境变量,如果无法正常执行可以尝试将其添加至 PATH 中。通常情况下,使用 pip 安装是无需添加至环境变量的(前提是 python 的路径在 PATH 中是正常的),使用脚本进行安装的情况下会在文件的末尾提示其安装位置,例如下文中的 {poetry_home_bin}
字段。
1 | Poetry ({version}) is installed now. Great! |
通常情况下,脚本会自动将 poetry 的路径添加至环境变量中,但部分情况下会无法正常添加,所以请一定要注意安装脚本的输出内容!如果添加失败的情况下,我们需要手动将 poetry 的可执行文件添加至环境变量中。
Linux下,通常的安装位置为 $HOME/.poetry/bin
,其中 $HOME
为你的用户根目录,例如 /home/well404
。我们可以通过 echo $HOME/.poetry/bin
来获取安装位置信息:
1 | well404@ubuntu2004:~$ echo $HOME/.poetry/bin |
并将获取到的信息与 export PATH=$PATH:
拼接,并写入到 .bash_profile
中(如果你用的是 bash 的话):
1 | # 选个你习惯的编辑器,例如 vi 或 nano |
Windows下,通常安装路径为 %USERPROFILE\.poetry\bin
,其中 %USERPROFILE
为你的用户目录,例如 C:\Users\Well404
。由于Windows无法直接通过命令行永久修改 PATH,且永久添加的方法步骤较多但有大量详细的教程,因此请自行查询添加方法,在此不多赘述。
poetry的基础使用
创建新项目
使用 poetry 新建名为 poetry-demo
的新项目:
1 | poetry new poetry-demo |
其创建的项目结构如下所示:
1 | poetry-demo |
其中,pyproject.toml
是用于存放项目信息的文件,例如项目名、版本号、依赖等,详情可以参考官方文档。
1 | [tool.poetry] |
简单来说,我们可以把这个文件看作高级版的 requirement.txt
,其中的信息会在创建项目的时候通过命令行的方式进行询问,因此根据你填入的信息不同,此文件的内容也不会完全相同。
不过,由于 poetry 的诞生早于 PEP621 的提出,其构筑方法与之并不兼容,因此 poetry 与后续所提到的 pdm 虽然都是使用 pyproject.toml
存放项目信息但二者并不兼容!
转化现有的项目
转化一个名为 pre-existing-project
的项目:
1 | cd pre-existing-project |
poetry 会对这个项目进行分析,并生成 pyproject.toml
文件,其过程类似于创建新项目的操作。
调整poetry设置
通过 poetry config --list
命令,我们可以查看 poetry 的设置。
通过 poetry config
命令,我们可以调节 poetry 的设置。例如:
1 | poetry config virtualenvs.create true |
在此,我们简单了解两个配置项:virtualenvs.create
和 virtualenvs.in-project
当参数 virtualenvs.create
为 true
时,执行 poetry install
或 poetry add
时会检测当前项目是否有虚拟环境,没有就自动创建,默认为 true
。
当参数 virtualenvs.in-project
为 true
时,虚拟环境的依赖将会放置于项目的文件夹内,而不是 poetry 默认的 {cache-dir}/virtualenvs
,默认为 false
。
通常情况下,笔者会将这两项均设置为 true
,这将简化我们的工作流程,以及更加方便的管理项目与其依赖。
使用poetry创建虚拟环境
通常我们会设置 virtualenvs.create=true
并且直接使用 poetry install
等命令来直接自动创建虚拟环境,不过我们也可以通过 poetry env use
手动创建虚拟环境,或通过 poetry env use <解释器路径>
来手动指定一个 python 解释器。例如:
poetry env use C:\Users\Well404\AppData\Local\Programs\Python\Python310\python.exe
此命令便是使用了安装在默认路径的 Python3.10 解释器进行项目的创建。
使用poetry激活虚拟环境
我们可以通过 poetry run 命令
来直接在该项目的虚拟环境中执行命令,也可以通过 poetry shell
来显式激活这个虚拟环境。
例如我们要运行这个虚拟环境中的 main.py
文件,便可使用 poetry run python main.py
或在 poetry shell
激活后直接输入 python main.py
。
使用poetry安装依赖
如果项目中已有 pyproject.toml
文件,可使用 poetry install
来直接安装其中所列出的依赖。poetry install --no-dev
参数以跳过 dev 使用的依赖,通常在部署项目时使用。
使用 poetry add <package>
可以在环境中安装新的依赖,例如 poetry add numpy
,也可以一次性添加多个依赖 poetry add requests pendulum
。
通过 --dev
参数可以指定为 dev 依赖,例如 poetry add pytest --dev
。
通过指定版本号也可限定依赖的版本范围,例如 poetry add pendulum@^2.0.5
或 poetry add "pendulum>=2.0.5"
。
其他常用命令
更多命令以及详细信息可查看官方文档中的介绍。
查看虚拟环境信息 poetry env info
显示虚拟环境所有列表 poetry env list
查看可以更新的依赖 poetry show --outdated
查看项目安装的依赖 poetry show
以树形结构查看项目安装的依赖关系 poetry show --tree
pdm
本段内容最后编辑于 2023/02/28,无法保证您看到时内容依旧具有时效性,如果发现过时或错误的内容可以通过文章开头的邮箱联系作者进行修改。
提到 pdm,我们绕不开的一点便是 PEP582。在这个提案中,抛弃虚拟环境是其核心诉求。
This PEP proposes to add to Python a mechanism to automatically recognize a
__pypackages__
directory and prefer importing packages installed in this location over user or global site-packages. This will avoid the steps to create, activate or deactivate “virtual environments”. Python will use the__pypackages__
from the base directory of the script when present.
简单来说,便是在一个项目的根目录中存放这个项目所用到的依赖,并在搜索依赖时优先使用项目根目录中的依赖,其次才会在 python 的 site-packages 中去找公共的依赖。
实际上,这一实现的目的与虚拟环境较为类似,都是通过一个独立的空间来存放与该项目相关的依赖信息,而相对于虚拟环境而言,PEP582 有3个非常明显的特点:
- 指定了一个相对固定的依赖存放位置
- 兼容公共依赖
- 并不需要激活/关闭虚拟环境
我们接下来介绍的 pdm 便是目前 PEP582 的实现,同时 pdm 也吸收了 PEP517 和 PEP621,相较于 poetry 在未来会有更强的兼容性。
但 pdm 也并不局限于 PEP582,pdm 也同时支持传统的虚拟环境(virtualenv 和 venv),而这也是目前绝大多数用户使用 pdm 的方法,也是笔者推荐的使用方法。PEP582 所设想的环境管理仍未得到广泛的支持,因此笔者并不建议在任何生产环境中使用这项尚未成熟的方案。
同时,pdm 的开发者 Frost Ming 是国人开发者,并且在项目中添加了中文版的 README,因此我们可以较为轻松的上手这个项目。
pdm 官方文档(英文):https://pdm.fming.dev/latest/
pdm github地址 :https://github.com/pdm-project/pdm
Frost Ming 的博客 :https://frostming.com/
虽然上文说了 pdm 这么多好话,但在笔者历时一个月的使用中发现了 pdm 仍然不适合刚入门的新手进行使用,同时老手也在部分情况下不得不使用其他虚拟环境管理工具来规避由 pdm 造成的 bug。
pdm vs poetry
pdm 的设计思路和操作逻辑很大程度上来源于 poetry,因此我们可以把二者看为一条赛道上的竞争关系。笔者在这里将以个人的使用体验来比较一下 pdm 与 poetry 的差异。
pdm 的优势:
- 更加友好的用户体验,其cli设计相对 poetry 更加友好与美观(rich nb)
- 对 PEP 的支持更加友好,更加符合 python 社区规范
- 能够直接定位已安装的 python 解释器,不用像 poetry 一样需要自己寻找解释器的位置。
pdm 的劣势:
- 在使用过程中可能碰到非常离谱的bug(有些是测试不全导致的bug,例如Issue1734,但有一些你都不知道这怎么可能发生的bug,例如找不到VC++的环境)
- 历史沉淀依然稀薄,用户数量并不多(这会导致现在使用很可能成为“第一个吃螃蟹的人”)
- 在某些小问题上 pdm 的处理需要让开发者额外操心(例如需要手动将 .pdm.toml 加入.gitignore或删除等)
虽然 pdm 拥有更美好的前景,但目前仍有不少bug需要修复,也有一些细节需要优化,与 poetry 相比在最重要的稳定性上仍略逊一筹。因此笔者在这里并不建议新手现在使用 pdm,但十分建议熟练的开发者更多的使用 pdm 并一起完善 pdm 生态。
总结
我们上述介绍的三个虚拟环境管理工具,笔者对其观点为:
- conda:非传统的实现,多版本python的首选,但不建议用于代替普通的虚拟环境(除非你硬盘很大)
- poetry:目前的主流,功能很强大,很长一段时间内不会过气
- pdm:新起之秀,战未来,国人开发,但目前仍然不建议新手使用
实际上,相对于学习 python 本身,python 的虚拟环境管理工具的难度都不是很高,并且我们也并不需要精通虚拟环境,仅需要知道如何安装,如何使用便足矣。