创建新的 virtualenv 时,会在该 virtualenv 中安装许多东西。 其中之一是python包安装程序pip。
在 Linux 上,pip 可执行文件是一个 shell 脚本。 在这个 pip shell 脚本的顶部是一个 shebang (#!) 行,它指定了 virtualenv 中的 python 解释器。 此行包含 python 解释器的绝对路径。
如果 virtualenv 中 python 解释器的绝对路径很长(深度嵌套和/或大路径名),它可能会超过 shebang 行允许的最大长度。
shebang 行的最大长度在内核中受到 BINPRM_BUF_SIZE 的限制,在 /usr/include/linux/binfmts.h 中设置。 在我查看的 Linux 机器上,此限制设置为 128。
因此,当创建 python virtualenv 的路径变得太长时,使用该 virtualenv 的 pip 将不起作用。 它将失败并显示错误:“错误的解释器:没有这样的文件或目录”
此问题的解决方法是不直接运行 pip,而是通过运行 virtualenv 的 python 解释器并将 pip 脚本传递给 python 作为执行源。
我也遇到这个问题。
我也是。
感谢您的解决方法!
请注意,包装器脚本实际上是由 setuptools(如果从 sdist 安装)或 distlib(如果从 wheel 安装)生成的。 因此,确实应该从这些项目中要求对此问题进行任何修复。
但是,如果这是操作系统限制,也许只是_不是_可行的解决方案? 我似乎记得有一次,Perl 使用了一种魔法咒语来执行脚本(谷歌有点......)是的,像这样(翻译为 Python)
#!/bin/sh
eval 'exec /the/long/interpreter/path/to/python $0 ${1+"$@"}'
您需要一些额外的东西,以便 Python 不会尝试执行 eval-exec 行,但这可能会奏效。
如果有人想提出类似的东西作为 setuptools 和 distlib 的功能请求,那就太好了。
因此,当创建 python virtualenv 的路径变得太长时,使用该 virtualenv 的 pip 将不起作用。
如果在发生此问题的系统上运行virtualenv
会_真的_很好,该命令将输出一些警告(甚至错误),表明位于具有如此长路径名的目录中基本上不受支持目前的默认值。
我也在打这个。 这对我来说是一个特别的问题,因为我在 Jenkins 构建中运行pip
,它有_非常_长的密码路径。 有趣的是,我有许多相同构建的构建从属(都将 BINPRM_BUF_SIZE 设置为 128,并且具有相同的 pip、python 和 virtualenv 版本)并且我在其中一些但不是其他人上遇到了这种情况,即使路径长度不同。
我喜欢@b-long 的建议; 如果virtualenv
将创建一个在当前系统上不起作用的包装器,它至少应该给用户一个警告,如果不是完全失败的话。
目前尚不清楚 virtualenv 如何检测到这种情况。 我们不能完全使用 C 头文件中的值,而且我不知道我们如何检测我们在具有此限制的系统上(Windows 没有,OSX 没有?)
我倾向于将此问题作为操作系统限制而不是 virtualenv 问题来解决。
对于它的价值,一些想法......
ctypes
可以这样做吗?# on Linux, BINPRM_BUF_SIZE == 128, giving us a maximum shebang length of 127
# 2 bytes for #!, 11 bytes for '/bin/python' leaves us with 114
if sys.platform() == 'Linux' and len(home_dir) > 114:
log.warn("bin/activate may not work your system, as the length of the shebang line will exceed 128 characters")
我相信其他用户也会欣赏我建议的更改。 我们可以让这个开放以供评论并激发公关吗? 谢谢@jantman和@pfmoore :smile:
BINPRM_BUF_SIZE
定义在内核头文件中,似乎只有少数内核函数使用。 我不相信有任何方法可以以编程方式检测到这一点(缺少读取标题,这几乎不可行)。
话虽这么说,我认为这是合理的假设,这不会很快改变任何时间(有最大长度认领的快速概览这里)。 当前长度也在execve(2) 手册页的“注释”部分中明确给出,其中指出,“#! 可执行 shell 脚本中的第一行允许的最大行长度为 127 个字符。”
我认为所有符合 POSIX 的操作系统都有某种限制,尽管其中一些,特别是 BSD 变体,可能有超过 8,000 个字符的限制。
虽然像我上面的建议那样简单地硬编码一些幼稚的东西似乎是一个合理的解决方案(如果平台是 Linux 并且行长度超过 127 个字符),但对我来说感觉过于粗糙、具体和不灵活。
我仍在考虑如何以不会给virtualenv
增加太多开销的方式以编程方式测试它(当然,我们只需要在 venv 创建时测试它,所以我d 假设一些开销可能是可以接受的)。
我有一些简单的概念验证代码来测试给定的路径是否是可接受的 she-bang 长度,但它相当难看,因为它将文件写到磁盘然后执行文件以捕获输出。 示例和输出在这里: https :
我将不得不把它称为一个晚上,但我会尽量回到这个。 我当然会感谢任何其他 Linux 用户或其他操作系统的用户的输入,他们可以确认他们是否有类似的限制。
与其尝试做一些棘手的事情,比如对限制进行假设,为什么不制作一个功能测试 bash 脚本呢? 如果 python 被正确调用,那么一切都很好,否则就不是。
重申:
setuptools
和distlib
- 代码不在 virtualenv 或 pip 中。关闭此问题,因为它不是 virtualenv 问题(您可以通过将完整的 Python 解释器安装到长目录名来获得相同的效果)。
我们刚刚遇到了这个问题。
为什么不使用 PATH 中的 python? virtualenv 已经在它前面加上了 bin 目录。
#!/usr/bin/env python
virtualenv 已经在它前面加上了 bin 目录
仅当您激活 virtualenv 时。 Virtualenv 支持在不激活的情况下使用。
如果有人觉得这令人困惑:
此问题的解决方法是不直接运行 pip,而是通过运行 virtualenv 的 python 解释器并将 pip 脚本传递给 python 作为执行源。
这意味着代替pip install -r requirements.txt
做python -m pip install -r requirements.txt
最有用的评论
如果有人觉得这令人困惑:
这意味着代替
pip install -r requirements.txt
做python -m pip install -r requirements.txt