如何让 virtualenv 在 Ubuntu 上使用 dist-packages?

Posted

技术标签:

【中文标题】如何让 virtualenv 在 Ubuntu 上使用 dist-packages?【英文标题】:How to get virtualenv to use dist-packages on Ubuntu? 【发布时间】:2013-10-13 04:58:44 【问题描述】:

我知道 virtualenv,如果在创建新的虚拟环境时没有传递 --no-site-packages 参数,会将 /usr/local/lib/python2.7/site-packages(对于 Python 2.7)中的包与新创建的虚拟环境链接。在 Ubuntu 12.04 LTS 上,我有三个可以安装 Python 2.7 包的位置(使用默认的 Ubuntu 提供的 Python 2.7 安装):

    /usr/lib/python2.7/dist-packages:这是我的 ipython、scipy、numpy、matplotlib 的全局安装——如果无法通过 scipy stack 获得它们,我会发现单独安装这些软件包(及其所有依赖项)既困难又费时。李> /usr/local/lib/python2.7/site-packages:这是空的,我认为除非我从源代码安装包,否则它将在 Ubuntu 上保持这种状态。 /usr/local/lib/python2.7/dist-packages:这里有非常重要的天文学本地包,尤其是与 PyRAF、STScI 等相关的包,单独安装非常困难和耗时。

请注意,我的系统上不存在诸如 /usr/lib/python2.7/site-packages 之类的全局目录。另请注意,我的 ipython、scipy 等全局安装让我可以即时使用这些包,而无需每次都获取/激活虚拟环境。

当然,我现在想使用 virtualenv 在我的用户主目录中创建一个虚拟环境,我将为我未来的项目获取/激活它。但是,我希望这个虚拟环境在创建时能够链接/复制上面列表中位置 (1) 和 (3) 中的所有包。造成这种情况的主要原因是我不想通过pip install 进程(如果可能的话)为这个(可能还有其他)虚拟重新安装 ipython、scipy、astro 包等环境。

这是我的问题:

    我有没有办法向 virtualenv 指定我希望它为将来创建的虚拟环境链接/复制这两个 dist-packages 目录中的包? 当我最终在两个 dist-packages 目录中更新我的 scipy、ipython 等全局安装时,这是否也会更新/更改我的虚拟环境使用的包(以及它最初在 virtualenv 创建期间获得的包)? 如果我曾经在 Ubuntu 上从源代码安装包,它会进入 /usr/local/lib/python2.7/dist-packages 还是 /usr/local/lib/python2.7/site-packages

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

这可能是PYTHONPATH 的合法使用——virtualenv 不涉及的环境变量,它使用与 bash 中的环境变量 PATH 相同的语法 PYTHONPATH=/usr/lib/python2.7/dist-packages:/usr/local/lib/python2.7/dist-packages 在 .bashrc 或类似文件中.如果你走这条路,

    您根本不必告诉您的虚拟环境,它不会尝试更改它。

    不需要重新链接,并且

    如果你将它们安装在你的虚拟环境之外,它仍然会去任何它应该去的地方(pip install 总是使用 /usr/local/lib/python2.7/dist-packages/ 对于我的 Ubuntu)。如果您从虚拟环境中安装它们(当它被激活时),那么它当然会被放入虚拟环境中。

【讨论】:

这很好用,谢谢!另一种方法是创建一个.pth 文件,其中每一行都是要添加到默认sys.path 的路径,并将该文件放在虚拟环境的站点包目录中,例如@ 中的dist-packages.pth 987654327@。我现在选择了后一种方法,因为它更清楚地说明了为什么这个特定的虚拟环境可以访问全局 dist-packages 目录,而不是 .bashrc 中的“全局”PYTHONPATH 环境变量。 啊,那也不错。有时我在虚拟环境中将一些东西添加到激活脚本中,您可以在那里设置和取消设置 PYTHONPATH,但由于 .pth 文件可以工作,这可能会更好。不过,它是处理其他类似事情的好地方。 这很好用。在按照这个答案规定的方式设置 PYTHONPATH 之前,我无法从 virtualenv pip install numpy。 使用 .pth 文件与配置管理配合得很好,因为在设置过程中将预制文件复制到适当的位置很简单。 我有 Ubuntu 14.04,对我来说,/usr/lib/python2.7 归 root 所有。我正在尝试运行使用 virtualenv(或任何必要的方法)来使用 Jenkins 运行 Python unittest 测试。我的 jenkins 系统用户无权访问这些目录。我宁愿不将我的 jenkins 用户添加到根组。我在这里做错了什么?【参考方案2】:

PYTHONPATH 为我工作。

vim ~/.bashrc

在下面添加这一行:

export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages:/usr/local/lib/python2.7/dist-packages
source ~/.bashrc

【讨论】:

如果 /usr/lib/python2.7/dist-packages 由 root 拥有并且您使用的是非 root 系统帐户怎么办?【参考方案3】:

您想要在这里实现的本质上是将特定文件夹 (dist-packages) 添加到 Python 搜索路径。为此,您有多种选择:

    使用路径配置 (.pth) 文件,条目将附加到系统路径。 修改PYTHONPATH(其中的条目转到系统路径的开头)。 直接从您的 Python 脚本修改 sys.path,即将所需的文件夹附加到它。

我认为对于这种特殊情况(启用全局dist-packages 文件夹),第三个选项更好,因为使用第一个选项,您必须为您将要工作的每个virtualenv 创建.pth 文件在(使用一些外部 shell 脚本?)。分发包裹时很容易忘记它。第二个选项需要运行时设置(添加一个 envvar),这也是很容易错过的。

只有第三个选项在配置或运行时不需要任何先决条件,并且可以毫无问题地分发(当然,在相同类型的系统上)。

你可以这样使用函数:

def enable_global_distpackages():
    import sys
    sys.path.append('/usr/lib/python2.7/dist-packages')
    sys.path.append('/usr/local/lib/python2.7/dist-packages')

然后在你的包的__init__.py 文件中:

enable_global_distpackages()

【讨论】:

【参考方案4】:

我只是在了解 virtualenv,但似乎有比目前提到的更简单的方法。

    因为virtualenv 1.7 --no-site-packages 一直是默认行为。 因此,使用--system-site-packages 标志到 virtualenv 是在你的路径中获取 dist 包所需要的全部 - 如果你使用 Ubuntu 提供的经过调整的 virtualenv。 (This answer 和 this one 给出了一些有用的历史记录)。我已经对此进行了测试,它确实有效。

    $ virtualenv --system-site-packages .

    我同意 Thomas 的观点 - 我看不到 virtualenv 中需要执行任何操作来查看 dist-packages 中更新的效果。

    已经用python setup.py install 测试过,它确实(再次如 Thomas 所说)仍然进入 dist-packages。你可以通过构建自己的 python 来改变这一点,但这有点极端。

【讨论】:

【参考方案5】:

site-packages目录下,创建文件dist.pth 在文件 dist.path 中,输入以下内容: ../dist-packages

现在停用并激活您的 virtualenv。你应该准备好了。

【讨论】:

以上是关于如何让 virtualenv 在 Ubuntu 上使用 dist-packages?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Ubuntu 20.04 GCP实例上安装virtualenv?

ubuntu 中虚拟环境的搭建

使用virtualenv在ubuntu上搭建python 3开发环境

试图让 OpenCV 3.2.0 与 virtualenv 一起工作

如何重置 virtualenv 和 pip?

在Ubuntu 20.04上安装Python虚拟环境