venv、pyvenv、pyenv、virtualenv、virtualenvwrapper、pipenv 等之间有什么区别?

What is the difference between venv, pyvenv, pyenv, virtualenv, virtualenvwrapper, pipenv, etc?

Python 3.3 在其标准库中包含新包 venv。它有什么作用,它与似乎匹配正则表达式 (py)?(v|virtual|pip)?env?

的所有其他包有何不同

这是我对初学者的个人建议: 从学习 virtualenv and pip 开始,这些工具与 Python 2 和 3 以及各种情况,并在开始需要时选择其他工具。

现在回答问题:venv、virtualenv 等这些名称相似的东西之间有什么区别?

PyPI 包不在标准库中:

  • virtualenv 是一个非常流行的工具,它为 Python 库创建隔离的 Python 环境。如果你不熟悉这个工具,我强烈建议学习它,因为它是一个非常有用的工具。

    它的工作原理是在目录中安装一堆文件(例如:env/),然后修改 PATH 环境变量以在其前面加上自定义的 bin 目录(例如:env/bin/)。 pythonpython3 二进制文件的精确副本放置在此目录中,但 Python 被编程为首先在环境目录中查找与其路径相关的库。它不是 Python 标准库的一部分,但得到了 PyPA(Python Packaging Authority)的正式认可。激活后,您可以使用 pip.

    在虚拟环境中安装软件包
  • pyenv用于隔离Python版本。例如,您可能想针对 Python 2.7、3.6、3.7 和 3.8 测试您的代码,因此您需要一种在它们之间切换的方法。激活后,它会在 PATH 环境变量前加上 ~/.pyenv/shims 前缀,其中有与 Python 命令匹配的特殊文件(pythonpip)。这些不是 Python 发送的命令的副本;它们是特殊的脚本,可以根据 PYENV_VERSION 环境变量、.python-version 文件或 ~/.pyenv/version 动态决定 Python 到 运行 的哪个版本文件。 pyenv 还使下载和安装多个 Python 版本的过程更容易,使用命令 pyenv install.

  • pyenv-virtualenvpyenv 的插件,作者与 pyenv 相同,可让您使用pyenvvirtualenv 同时方便。但是,如果您使用 Python 3.3 或更高版本,pyenv-virtualenv 将尝试 运行 python -m venv(如果可用),而不是 virtualenv。如果您不想要这些便利功能,可以同时使用 virtualenvpyenv 而不用 pyenv-virtualenv

  • virtualenvwrapper is a set of extensions to virtualenv (see docs)。它为您提供 mkvirtualenvlssitepackages 等命令,尤其是 workon 用于在不同的 virtualenv 目录之间切换。如果您想要多个 virtualenv 个目录,此工具特别有用。

  • pyenv-virtualenvwrapper是与pyenv同一作者的pyenv插件,方便集成virtualenvwrapper 变成 pyenv.

  • pipenv旨在将Pipfilepipvirtualenv合并为一个命令命令行。 virtualenv 目录通常放在 ~/.local/share/virtualenvs/XXX 中,XXX 是项目目录路径的散列。这与 virtualenv 不同,后者的目录通常位于当前工作目录中。 pipenv 用于开发 Python 应用程序(相对于库)。 pipenv 有替代方案,例如 poetry,我不会在这里列出,因为这个问题只是关于名称相似的包。

标准库:

我会避免在 Python3.3+ 之后使用 virtualenv,而是使用标准的附带库 venv。要创建新的虚拟环境,您可以键入:

$ python3 -m venv <MYVENV>  

virtualenv 尝试将 Python 二进制文件复制到虚拟环境的 bin 目录中。但是它不会更新嵌入到该二进制文件中的库文件链接,因此如果您将 Python 从源代码构建到具有相对路径名的非系统目录中,则 Python 二进制文件会中断。由于这是使副本可分发的方式 Python,这是一个很大的缺陷。顺便说一句,要检查 OS X 上的嵌入式库文件链接,请使用 otool。例如,在您的虚拟环境中,键入:

$ otool -L bin/python
python:
    @executable_path/../Python (compatibility version 3.4.0, current version 3.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

因此我会避免 virtualenvwrapperpipenvpyvenv 已弃用。 pyenv 似乎经常在使用 virtualenv 的地方使用,但我也会远离它,因为我认为 venv 也可以完成 pyenv 的功能。

venv 在 shell 中创建 freshsandboxed 的虚拟环境,其中 用户可安装的库多python安全

Fresh:因为虚拟环境仅从 python 附带的标准库开始,您必须使用 [=24= 重新安装任何其他库] 当虚拟环境处于活动状态时。

Sandboxed:因为 none 这些新库安装在虚拟环境之外是可见的,所以你可以删除整个环境并重新开始而不用担心影响你的基本 python 安装。

用户可安装库:因为虚拟环境的目标文件夹是在您已经拥有的某个目录中没有sudo创建的,所以您不需要sudo 将库安装到其中的权限。

multi-python safe:因为当虚拟环境激活时,shell 只能看到 python 版本(3.4、3.5 等.) 用于构建该虚拟环境。

pyenvvenv 相似,因为它允许您管理多个 python 环境。但是,使用 pyenv 后,您无法方便地将库安装回滚到某个启动状态,并且在某些时候您可能需要 admin 权限来更新库。所以我觉得也最好用venv.

在过去的几年里,我在构建系统(emacs 包、python 独立应用程序构建器、安装程序...)中发现了很多问题,这些问题最终归结为 virtualenv 的问题。我认为 python 将是一个更好的平台,当我们消除这个额外的选项并且只使用 venv.

编辑:BDFL 的推文,

I use venv (in the stdlib) and a bunch of shell aliases to quickly switch.

— Guido van Rossum (@gvanrossum) October 22, 2020

更新 20200825:

在“结论”段落下方添加

我已经进入 pipenv 兔子洞(这确实是一个又深又黑的洞...)并且 由于上一个答案是 2 年多以前,我觉得用我发现的 Python 虚拟信封主题的最新进展来更新讨论很有用。

免责声明:

这个答案 NOT 关于继续关于 pipenv 优点的激烈辩论 venv作为信封解决方案- 我不认可任何一个.这是关于 PyPA 认可相互冲突的标准以及 virtualenv[=133 的未来发展=] 承诺完全否定在它们之间做出 either/or 的选择。我专注于这两个工具正是因为它们是 PyPA.

的受膏者

文夫

正如 OP 所指出的,venv 是一种用于虚拟化环境的工具。 不是第三方解决方案,而是本机工具。 PyPA 支持 venv 创建 虚拟信封:“Changed in version 3.5: The use of venv is now recommended for creating virtual environments”。

pipenv

pipenv-喜欢venv-可用于创建虚拟信封,但另外引入包管理和 vulnerability checking functionality. Instead of using requirements.txt, pipenv delivers package management via Pipfile. As PyPA endorses pipenv for PACKAGE MANAGEMENT,这似乎暗示 pipfile 将取代 requirements.txt.

HOWEVER: pipenv 使用 virtualenv 作为创建虚拟信封的工具,NOT venv PyPA 认可它是创建虚拟信封的首选工具。

冲突的标准:

因此,如果解决虚拟信封解决方案还不够困难,我们现在有 PyPA 支持两种使用不同工具的不同工具虚拟信封解决方案。关于 venv vs virtualenv 的激烈 Github 争论可以在 here.

中找到,它强调了这一冲突

冲突解决:

上面 link 中提到的 Github 辩论已经引导 virtualenv 朝着适应 venvfuture releases:

prefer built-in venv: if the target python has venv we'll create the environment using that (and then perform subsequent operations on that to facilitate other guarantees we offer)

结论:

所以看起来这两个竞争性虚拟信封解决方案之间会有一些未来的融合,但截至目前 pipenv-使用 virtualenv - 从 venv.

变化 material

考虑到 the problems pipenv solvesPyPA 的祝福,它 看来前程似锦。如果 virtualenv 实现了其提议的开发目标,那么选择虚拟信封解决方案将不再是 pipenvvenv.

更新20200825:

我在生成此分析时看到对 Pipenv 的一个经常批评是它没有得到积极维护。事实上,使用一个由于缺乏持续发展而前途堪忧的解决方案有什么意义呢?在经历了大约 18 个月的枯竭之后,Pipenv 再次被积极开发。事实上,大型 material 更新已经 released

2020 年 1 月更新

@Flimm 已经很好地解释了所有差异。通常,我们想知道所有工具之间的区别,因为我们想决定什么是最适合我们的。所以,下一个问题是:使用哪个?我建议您选择两种官方方式之一来管理虚拟环境:

  • pyenv - 管理不同的 python 版本,
  • 所有其他人 - 创建虚拟环境(已隔离 python 版本和安装的“要求”),

pipenv 想要结合所有,除了之前安装“要求”(进入活动虚拟环境或创建自己的 如果 none 处于活动状态)

所以也许你只会对 pipenv 感到满意。

但我使用:pyenv + pyenv-virtualenvwrapper, + pipenv(pipenv 仅用于安装需求)。

在 Debian 中:

  1. apt install libffi-dev

  2. 基于https://www.tecmint.com/pyenv-install-and-manage-multiple-python-versions-in-linux/安装pyenv,但是..

  3. .. 但不是 pyenv-virtualenv 安装 pyenv-virtualenvwrapper (可以是独立库或 pyenv 插件,这里是第二个选项):

    $ pyenv install 3.9.0
    
    $ git clone https://github.com/pyenv/pyenv-virtualenvwrapper.git $(pyenv root)/plugins/pyenv-virtualenvwrapper
    # inside ~/.bashrc add:
    # export $VIRTUALENVWRAPPER_PYTHON="/usr/bin/python3"
    $ source ~/.bashrc
    
    $ pyenv virtualenvwrapper
    

然后为您的项目创建虚拟环境(workingdir 必须存在):

pyenv local 3.9.0  # to prevent 'interpreter not found' in mkvirtualenv
python -m pip install --upgrade pip setuptools wheel
mkvirtualenv <venvname> -p python3.9 -a <workingdir>

并在项目之间切换:

workon <venvname>
python -m pip install --upgrade pip setuptools wheel pipenv

在一个项目中,我有文件 requirements.txt,但没有修复其中的版本(如果不需要某些版本限制)。 您有 2 个可能的工具可以将它们安装到当前的虚拟环境中:pip-toolspipenv。假设您将使用 pipenv:

pipenv install -r requirements.txt

这将创建 Pipfile 和 Pipfile.lock 文件,固定版本在第二个中。如果你想在某个地方重新安装完全相同的版本,那么(Pipfile.lock 必须存在):

pipenv install

请记住,Pipfile.lock 与某些 Python 版本相关,如果您使用其他版本,则需要重新创建。

如你所见我写requirements.txt。这有一些问题:您还必须从 Pipfile 中删除已删除的包。所以直接写Pipfile可能更好。

所以你可以看到我用pipenv很差。说不定只要你用得好,它就能代替一切?

编辑 2021.01:我已将堆栈更改为:pyenv + pyenv-virtualenvwrapper + poetry。 IE。我没有使用 virtualenv 或 virtualenvwrapper 的 apt 或 pip 安装,而是安装 pyenv 的插件 pyenv-virtualenvwrapper。这是更简单的方法。

Poetry 对我来说很棒:

poetry add <package>   # install single package
poetry remove <package>
poetry install   # if you remove poetry.lock poetry will re-calculate versions

让我们从这些工具想要解决的问题开始:

我的系统包管理器没有我想要的 Python 版本,或者我想并排安装多个 Python 版本,Python 3.9。 0 和 Python 3.9.1、Python 3.5.3 等

然后使用pyenv

我想安装 运行 多个具有不同的、相互冲突的依赖项的应用程序。

然后使用virtualenv 或venv。它们几乎完全可以互换,不同之处在于 virtualenv 支持旧的 python 版本并且有一些更小的独特功能,而 venv 在标准库中。

我正在开发一个 /application/ 并且需要管理我的依赖项,并管理我项目的依赖项的依赖项解析。

那就用pipenv或者poetry吧

我正在开发一个 /library/ 或一个 /package/ 并且想指定我的库用户需要安装的依赖项

然后使用setuptools。

我使用了 virtualenv,但我不喜欢 virtualenv 文件夹分散在各个项目文件夹中。我想要集中管理环境和一些简单的项目管理

然后使用virtualenvwrapper。变体:pyenv-virtualenvwrapper 如果你也使用 pyenv。


不推荐

  • pyvenv。这已被弃用,请改用 venv 或 virtualenv。不要与 pipenv 或 pyenv 混淆。

作为一个 Python 新人,这个问题让我无休止地沮丧,并困惑了我几个月。当我知道我将在未来几年使用它时,我应该投资学习哪个虚拟环境和包管理器?

回答这个棘手问题的最佳文章是 Jake Vanderplas 的 https://jakevdp.github.io/blog/2016/08/25/conda-myths-and-misconceptions/。虽然已有几年历史,但它提供了实用的答案以及 Python 包和虚拟环境管理器的历史,因为这些最先进的技术正在开发中。

在数据科学和“大数据云计算”社区中,这让我特别沮丧,因为 conda 被广泛用作 Python 和 [=71= 的虚拟环境管理器和全功能包管理器]Script、SQL、Java、HTML5 和 Jupyter 笔记本。

那么,当 conda 可以完成 pip 和 venv 变体所做的一切时,为什么还要使用 pip?

答案是,“因为如果 conda 包根本不可用,您必须使用 pip。”很多时候所需的包只能以 pip 格式提供,除了使用 pip 之外没有简单的解决方案。你可以学习使用 conda build 但如果你不是包维护者,那么你必须说服包所有者为每个新版本生成一个 conda 包(或者自己做。)

这些基于 pip 的软件包在许多重要和实用方面有所不同:

  • 稳定性
  • 成熟度
  • 复杂性
  • 主动支持(相对于垂死或死亡)
  • Python 生态系统“核心”附近的采用水平与“上” 边缘”(即集成到 Python.org 发行版中)
  • 易于理解和使用(适合初学者)

我会从包的成熟度和稳定性的维度回答你两个包的问题。

venv 和 virtualenv 是最成熟、最稳定、最有社区支持的。从联机文档中,您可以看到 virtualenv 的版本为 20.x。 virtualenv

virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. The venv module does not offer all features of this library, to name just a few more prominent:

is slower (by not having the app-data seed method),

is not as extendable,

cannot create virtual environments for arbitrarily installed python versions (and automatically discover these),

is not upgrade-able via pip,

does not have as rich programmatic API (describe virtual environments without creating them).

virtualenvwrapper 是一组帮助人们使用 virtualenv 的脚本(它是一个维护得不好的“包装器”,它的最后一次更新是在 2019 年。virtualenvwrapper

我的建议是尽可能避免所有 pip 虚拟环境。请改用 conda。 Conda 提供了统一的方法。它由专业的开源开发人员团队维护,并有一家信誉良好的公司提供资金和商业支持的版本。相比之下,维护 pip、venv、virtualenv、pipenv 和许多其他 pip 变体的团队资源有限。 pip 虚拟环境的多样性让初学者感到沮丧。基于 pip 的虚拟环境工具的复杂性、碎片化、边缘和不受支持的包,以及极不一致的支持促使我使用 conda。对于数据科学工作,我的建议是在不存在 conda 包的情况下,使用基于 pip 的虚拟环境管理器作为最后的手段。

venv 变体之间的差异仍然让我感到害怕,因为我学习新包的时间有限。 pipenv, venv, pyvenv, pyenv, virtualenv, virtualenvwrapper, poetry 和其他有几十个差异和复杂性,需要几天时间才能理解。我讨厌沿着这条路走下去,发现当维护者辞职(或太忙而无法维护它)时,对包的支持就会崩溃。我只需要完成我的工作。

本着乐于助人的精神,这里有一些链接可以帮助您深入了解,但不会迷失在但丁的地狱(回复:pip)中。

A Guide to Python’s Virtual Environments

选择“核心”Python 套餐来为您的职业(长期)投资,而不是短期完成工作)很重要。但是,这是一道商业分析题。您是想简单地完成一项任务,还是想要构建可扩展的高性能系统的专业软件工程师,这些系统随着时间的推移需要最少的维护工作?恕我直言,conda 会比处理 pip-plurality 问题更容易将您带到后者。 conda 仍然缺少 1-step pip-package 迁移工具,这使这个问题成为一个有实际意义的问题。如果我们可以简单地将 pip 包转换为 conda 包,那么 pypi.org 和 conda-forge 可以合并。 Pip 是必需的,因为 conda 包(还)不是通用的。许多 Python 程序员要么懒得创建 conda 包,要么他们只在 Python 中编程并且不需要 conda 的语言无关/多语言支持。

conda 对我来说是天赐之物,因为它支持云软件工程和数据科学对 JavaScript、SQL、Jupyter Notebook 扩展和 conda 播放的多语言支持的需求在 Docker 和其他云原生环境中。我鼓励您学习和掌握 conda,这将使您能够回避许多基于 pip 的工具可能永远无法回答的复杂问题。

保持简单!我需要一个包来完成我需要的 90% 的功能,并为剩余的 10% 的边缘情况提供指导和解决方法。

查看此处链接的文章以了解有关基于 pip 的虚拟环境的更多信息。

我希望这对原始发布者有所帮助,并给 pip 和 conda 爱好者一些思考。

这就是拥有统一包和环境管理器的动机。 Pythonista 也是通晓多种语言,

减少复杂性,简化生活

“应该有一种——最好只有一种——显而易见的方法。”

Python 的禅宗,蒂姆·彼得斯

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!