有关此问题的摘要,请参阅https://github.com/pypa/pip/issues/2195#issuecomment -524606986。
我怀疑为什么 pip 需要 17 秒来处理 pip 不在 NFS 上的本地目录(实际上,它在 SSD 驱动器上),因为 pip 没有依赖关系,因为一切都是供应商提供的。
$ time pip install --no-install ~/dev/git-repos/pip
DEPRECATION: --no-install and --no-download are deprecated. See https://github.com/pypa/pip/issues/906.
Processing /Users/marca/dev/git-repos/pip
Requirement already satisfied (use --upgrade to upgrade): pip==6.0.dev1 from file:///Users/marca/dev/git-repos/pip in /Users/marca/dev/git-repos/pip
pip install --no-install ~/dev/git-repos/pip 2.80s user 5.86s system 50% cpu 17.205 total
它可能至少应该记录花费那么长时间的任何事情,但也许它甚至不应该做任何它正在做的事情。
请注意,“处理”行立即出现,几乎整个延迟似乎都在该行和下一行之间。
它正在制作整个目录的副本,包括.git
。 它可能不应该这样做,不。
$ du -sh pip
263M pip
$ du -sk * .cache .git .tox .travis | sort -nr | head -n 5
181860 .tox
34836 tests
31700 .git
9212 pip
2852 build
我尝试传递 3 -v
's ( time pip install -vvv --no-install ~/dev/git-repos/pip
) - 没有产生更多信息。
使用 pdb 逐步完成,当我到达时,事情会变慢:
> /Users/marca/dev/git-repos/pip/pip/req/req_set.py(365)prepare_files()
-> unpack_url(
是的, @tomprince是对的 - 当它复制整个树时它会变慢:
> /Users/marca/dev/git-repos/pip/pip/download.py(635)unpack_file_url()
-> shutil.copytree(link_path, location, symlinks=True)
$ time pip install --no-install ~/dev/git-repos/pip
DEPRECATION: --no-install and --no-download are deprecated. See https://github.com/pypa/pip/issues/906.
Processing /Users/marca/dev/git-repos/pip
2014-12-15 15:23:34.630794: Copying tree; link_path = '/Users/marca/dev/git-repos/pip'; location = '/var/folders/gw/w0clrs515zx9x_55zgtpv4mm0000gp/T/pip-D6etc4-build'
2014-12-15 15:23:57.418679: DONE copying tree; link_path = '/Users/marca/dev/git-repos/pip'; location = '/var/folders/gw/w0clrs515zx9x_55zgtpv4mm0000gp/T/pip-D6etc4-build'
Requirement already satisfied (use --upgrade to upgrade): pip==6.0.dev1 from file:///Users/marca/dev/git-repos/pip in /Users/marca/dev/git-repos/pip
pip install --no-install ~/dev/git-repos/pip 2.75s user 5.03s system 32% cpu 24.168 total
>>> elapsed time 24s
现在https://github.com/pypa/pip/pull/2196合并了,速度要快得多。
这应该重新打开,因为 #2196 已恢复。 我想提供一个替代 PR 来构建一个 sdist 而不是使用启发式来找出要复制的内容。 有关详细信息,请参阅对该 PR 的评论。
$ time pip install --no-install ~/dev/git-repos/pip
DEPRECATION: --no-install and --no-download are deprecated. See https://github.com/pypa/pip/issues/906.
Processing /Users/marca/dev/git-repos/pip
Requirement already satisfied (use --upgrade to upgrade): pip==6.1.0.dev0 from file:///Users/marca/dev/git-repos/pip in /Users/marca/dev/git-repos/pip
pip install --no-install ~/dev/git-repos/pip 3.67s user 8.12s system 7% cpu 2:45.83 total
>>> elapsed time 2m46s
哎呀,快3分钟了。
大概是因为这个:
$ du -sh .tox
177M .tox
.tox
目录是我整个pip
目录总共 270M 中的 177M。
请参阅https://github.com/pypa/pip/pull/2535 ,它通过构建 sdist 并解包来加速unpack_file_url
。
这个问题应该重新打开,因为合并的 PR 什么也没做(参见 gh-3219)。
这个问题有什么进展吗?
不,而且看起来最终解决方案不会很快到来。 PEP 516 或 PEP 517 需要接受才能决定首先生成sdist
是否正确(我个人不这么认为)。
PEP 516 将其总结为:
Being able to create new sdists from existing source trees isn't a thing pip does today,
and while there is a PR to do that as part of building from source, it is contentious and
lacks consensus.
可能最简单的方法是让某人提交一个更简单的 PR 来修复最愚蠢的行为,比如复制所有的.git
和.tox
(假设今天仍然发生)。 在许多情况下,这将是一个显着的加速,并且没有争议。
在 npm 中从裸仓库(而不是源代码分发,或者我应该说已发布的包)安装时要做什么类似的问题 -为 git url 包运行prepublish
@rgommers如何添加一个文件.pipignore
来列出要忽略的文件和目录,如.gitignore
而不是硬编码某些文件/目录名称,如.git
和.tox
?
这不是一个好主意 - 它将处理这种缓慢的责任转移到每个包的开发人员身上,这就是行不通的。
如果 npm 有它一定很好:) – https://docs.npmjs.com/misc/developers#keeping -files-out-of-your-package
这也积极地破坏了 setuptools_scm 之类的东西 ^^ - pip install 制作文件夹副本已经很困难了
setuptools_scm 与它有什么关系? 它应该在有效的 repo 上运行,而不是任何类型的源包。
这不是一个好主意 - 它将处理这种缓慢的责任转移到每个包的开发人员身上,这就是行不通的。
让 .pipignore 隐含地包含 .git、.hg 等,而空的 .pipignore 会抑制这个。
@piotr-dobrogost 从源代码库安装 pip 会在 pip 没有复制足够上下文的各种情况下中断 - 例如 pypa/setuptools_scm#138
我们之前确实忽略了像.git
类的目录,并且破坏了 pbr 之类的东西,不得不恢复更改。
@dstufft如果它位于 git repo 的
嗯,如果破损已经够严重了,那么这里就没有简单的方法可以改进了。 猜猜它正在等待其中一个构建 PEP。
如果 pbr 在没有.git
目录的情况下摔倒了,它一定是在做一些非常不合理的事情,但是......
想知道这方面是否有任何进展? 不仅.git
或任何.${scm}
文件夹很麻烦,如果人们将.vagrant/
与源一起包含在内,情况会更糟。
拥有一个可定制的.pipignore
真的有助于减轻痛苦。
对于另一个数据点; 我们在一些项目中混合使用了 Python 和 Javascript,因为我们使用 Sphinx 来记录我们的 Javascript 项目。 因此,pip 也在复制一个非常大的node_modules
目录,这可能会非常缓慢。
因此,我们将投票支持.pipignore
选项,因为我们的用例强调硬编码值不一定适用于所有类型的项目。
人们确实在 SCM 文件之外的树中保留了各种垃圾。
我有一些由我与包源代码保存在同一目录中的代码生成的大型模拟(16GB +)(作为跟踪不同项目的一种方式)。
pip install .
它们复制到我的 /tmp。 糟糕的分区实际上用完了空间并且 pip 因磁盘空间错误而失败。
如果不应该使用sdist,并且.pipignore扩展了接口,那么重用解析MANIFEST.in/MANIFEST文件的代码呢? 它应该描述了安装所需的所有文件。
一个好的解决方法似乎是使用可编辑的安装 ( pip install -e $DIR
)。
一个好的解决方法似乎是使用可编辑的安装(pip install -e $DIR)。
除了测试之外,这不会测试用户从 pypi 安装软件包将使用什么。 (例如,未打包的包和模块仍然可用)
我希望这在这个线程之前已经提到过。
更好的解决方法是直接使用 setup.py 构建 sdist 或轮子,并使用 pip 安装生成的工件。 这样,pip 就不会执行目录复制操作(因为它有一个要安装的文件),这与使用pip install .
(从 pip 9 开始)完全相同的结果,减去目录复制。
看在上帝的份上,伙计们,这可以以某种方式解决吗? 我的意思是,似乎有一些共识认为这种行为是脑残 - 但现在票已经开放三年了,而且看不到解决方案。 我讨厌必须手动将数据移入和移出我的树,这样 pip 就不会停止或挂起几分钟(我必须在共享文件系统上工作)。
如果没有就如何不破坏现有工作达成共识,是否可以提供像.pipignore
这样的解决方案作为选择加入? 我不介意跳过一些箍来解决这个问题。
@andre-merzky 请冷静。
我们知道这个问题,但我们是一个资源非常有限的志愿者组织。 实际上,这个问题对我们的用户影响不够严重,不足以排在优先级列表的前列。
它会在适当的时候得到修复(我们目前正在努力解决的更重要的工作,特别是 PEP 517,可能会作为副作用解决这个问题),但对志愿者大喊大叫无济于事。 如果您认为立即修复很重要,我们很乐意审核 PR - 但您应该意识到,即使您确实提出了 PR 并被接受,它也不会在 PIP 10 之前发布,那就是我们希望至少获得一些我上面提到的“大票”工作的发布(由于志愿者资源的限制,它可能不会再次发生,但这是我们的目标)。 所以它可能会在发布之前被取代——但这并不意味着你不欢迎创建 PR,如果更大的计划没有及时实现,这将是一个后备。
@pfmoore对语气感到抱歉,说的是沮丧......我为一个微不足道的(因此可能是不可接受的)修复创建了一个 PR (#4900)。 我听说你在发布周期,事情就是这样,我知道......
也遇到了这个:
(env) $ find node_modules/ | wc -l
140287
(env) $ time pip install .
Processing /path/to/myproject
Installing collected packages: myproject
Running setup.py install for myproject ... done
Successfully installed myproject-1.0
real 4m35.598s
user 0m6.928s
sys 0m7.992s
重置后:
(env) $ mv node_modules/ ../
(env) $ time pip install .
Processing /path/to/myproject
Installing collected packages: myproject
Running setup.py install for myproject ... done
Successfully installed myproject-1.0
real 0m0.899s
user 0m0.496s
sys 0m0.120s
有关该问题的最新分析报告在哪里?
这里没有变化。 今天,pip 仍在将整个包复制到临时构建目录。
这个目录在内存中吗?
不,它写入磁盘 - 这使得它在共享文件系统上特别痛苦......
至少在/tmp
或/dev/shm
吗? https://stackoverflow.com/questions/9745281/tmp-vs-dev-shm-for-temp-file-storage-on-linux它可以检测到何时没有使用tmpfs
并建议创建一个吗?
它在/tmp
。 这取决于标准库tempfile
。
实施 PEP 517 将解决这个问题。
我在使用最新的 pip 开发人员版本时遇到了这个问题 - 我认为 PEP 517 支持已添加到 pip 19 中,所以这仍然会发生吗?
就我而言,因为我在一个项目 (astropy) 上工作,其中有许多遥控器和分支,所以我的 .git 目录是 1.8Gb,将它复制到临时目录需要几分钟。 似乎首先构建源代码分发然后在幕后从那里构建轮子更有意义。
由于这个问题,我们仍然受到很大的伤害。 很难告诉我们的用户他们不能将代码和实验数据(很大)保存在同一目录中 - 这非常违反直觉。 在我们自己的系统上,我们使用.pipignore
补丁,但无法在我们支持的大多数系统上部署它...:/
我们今天也遇到了这个https://github.com/pypa/pip/issues/2195#issuecomment -351258913。 它仍在发生。
(venv) (venv) pip --version
pip 19.1.1 from /application/venv/lib/python2.7/site-packages/pip (python 2.7)
实施 PEP 517 将解决这个问题。
旁白:没有。
解决这个问题需要通过 sdist 进行安装,上次我们讨论过这个问题时,使用工具(显然)需要实际源目录的人有很多反对意见。 我个人认为,我们应该咬紧牙关,不建议使用的构建过程,当你这样做不给相同的结果build_sdist
然后build_wheel
为你当你只是做build_wheel
,但我目前没有时间或精力支持这个提议。
解决这个问题需要通过 sdist 安装
实际上,没有 - #4900 提供了一个实现,它以向后兼容的方式用很少的代码解决了这个问题。 它可能无法解决其他问题 - 但鉴于这张票的年龄,我想要求重新考虑这种方法。
解决这个问题需要通过 sdist 进行安装,上次我们讨论过这个问题时,使用工具(显然)需要实际源目录的人有很多反对意见。 就我个人而言,我认为我们应该咬紧牙关并弃用在执行 build_sdist 和 build_wheel 时不会产生与执行 build_wheel 时得到的结果相同的构建过程,但我没有时间或精力亲自支持该提案在这一刻。
作为关心就地构建并因此不喜欢“必须始终通过 sdist 路线”的人:我很久以前就已经接受了“走 sdist 路线”。
如果你遇到这个问题会_非常_痛苦,并且“默认复制所有内容”毫无意义。 所以+10硬着头皮。
解决这个问题需要通过 sdist 安装
我错误地认为我们会使用 PEP 517 进行转换。
不过,我完全同意你的看法。
IIRC 我们本来可以做的,但是它会引发关于通过 sdist 安装是否可以接受的辩论,当时有太多额外的争议无法添加 - 由于通过复制和构建轮子安装仍然是一种选择,我采取了压力较小的方式课程 :-)
我仍然更喜欢通过 sdist 切换到构建,但我现在没有时间自己做。
解决方法:使用浅克隆(更改深度以适应):
cd d:\code
git clone --depth=100 https://github.com/PROJECT/PROJECT.git d:/code/shallow-PROJECT
move d:\code\PROJECT d:\code\PROJECT-bloated
move d:\code\shallow-PROJECT d:\code\PROJECT
重申和总结:
现在,走这条路线还解决了围绕 pip 为用户构建机制的一系列其他可用性问题。
我已经开始了一个自我激励的项目来重构 pip 的构建逻辑。 虽然我不会将这个问题作为重构工作的一部分来解决,但我非常愿意帮助那些愿意尝试解决这个问题的人——这个修复将相当涉及 pip 的构建逻辑,这是这不是最直接的代码,可能会有我们只在实现过程中注意到的棘手的边缘情况。
哦,作为对此的创可贴解决方法,在#6770 中添加,pip 19.3 将在复制时排除.nox
和.tox
目录。 对于相当多的用户来说,这应该会减少这些安装所需的时间。
这不能解决大型.git
或build
目录的问题——这就是我在上面的评论中阐述的方法将解决的问题。 :)
这不能解决大型
.git
或build
目录的问题——这就是我在上述评论中阐述的方法将解决的问题。 :)
我知道有些工具依赖于.git
,但是有人依赖build
被复制吗? 添加到忽略的目录中会很好,如果您同意,很高兴发送 PR。
这还在调查中吗? 看到在pip install .
期间复制了多 GB 的 git-ignored 调试数据转储,这是一个非常痛苦的惊喜
是的,请查看链接的问题,例如 #7555。
这个问题仍然存在,因为我从中安装的目录可能有 10 mb 的 python 代码,但是有很多 json 数据文件和.git
。
这应该由 #7882 解决(就地构建本地目录)。
我们现在(根据 #7951)发布了 pip 的 beta 版本,pip 20.1b1。 此版本包括#7882,它为此问题实施了解决方案。
我希望这个问题的参与者通过测试 beta 和检查新的错误来帮助我们。 我们希望在周二发布 20.1 主要版本之前确定并解决所有潜在问题。
我也欢迎“是的,现在效果更好了!”的积极反馈。 同样,因为问题跟踪器通常充满了“问题”。 :)
我会说它要好得多。
旧: noglob pip3 install . 3.76s user 2.51s system 12% cpu 50.245 total
新: noglob pip3 install . 3.40s user 0.70s system 42% cpu 9.764 total
对我来说效果很好/更快! :+1:
» pip --version
pip 20.0.2
» time pip install .
noglob pip install . 8.03s user 18.47s system 25% cpu 1:44.84 total
» pip --version
pip 20.1b1
» time pip install .
noglob pip install . 3.69s user 0.31s system 92% cpu 4.307 total
从 2 分钟缩短到 4 秒,非常感谢!
感谢您的积极报道@PythonCoderAS @astrofrog @klamann! :)
不幸的是,就地构建的实施存在许多问题(正在#7555 下跟踪),这意味着现在,我们需要恢复#7882。 因此,这个问题将再次成为问题,因此我们将重新打开它。 从长远来看,我们希望有一个解决方案来解决就地构建解决的问题,但不会影响当前解决方案对其他工作流程的影响。
很抱歉这会造成中断。
不幸的是,就地构建的实施存在许多问题
@pradyunsg感谢您的更新。 关于术语的一些反馈(请随意忽略,仅供参考):这句话以及 gh-7555 使我感到困惑,因为 pip 不进行就地构建。 就地构建一直意味着python setup.py build_ext --inplace
(或python setup.py develop
)。
在这里,您将含义更改为:“无需复制到 tmpdir 即可构建”。 扩展模块仍然没有就地结束,它们最终在build/
目录中,通常很容易清理。 在例如 gh-7555 中更明确一点会很好。
这原本是我的措辞。 抱歉有任何混淆,我不知道 setuptools 使用术语“就地”来表示不同的意思(我仍然不确定该术语如何应用于 setuptools 之外)。 我们会看看我们将来是否能找到一个更中性的术语(虽然是草率的,我不确定是什么 - 感激地接受建议 😉)
完全不用担心,谢谢@pfmoore。 我只是想我会指出这一点,因为术语的混淆有时会导致相互交谈。
我仍然不确定该术语如何应用于 setuptools 之外
对于像 CMake 和 scikit-build 这样的工具,我认为这意味着同样的事情:实际上就地,二进制文件位于源旁边。
另一方面,“可编辑安装”是(我相信)在这里发明的,有点意思是“pip 知道的就地”。
虽然是草率的,但我不确定是什么 - 感激地接受了建议
也许只是“本地构建”(与当前的“复制到 tmpdir 并构建”相比)?
另一方面,“可编辑安装”是(我相信)在这里发明的,有点意思是“pip 知道的就地”。
我们最近对可编辑安装的含义进行了长时间的讨论,我认为就 pip 而言,我们实际上进入了一个更接近machine local
地方。 但是 pip 不知道本地机器上的位置和方式,并且是构建后端工作来定义和处理它。
可以尝试«in-tree build»(类似于«in-tree PEP 517 backend»)或«build in source dir»
我的问题是,为什么该功能不能是可选的,所以它不会引起问题,但可以通过参数或类似的东西启用?
我正在尝试解决这个问题,其中不可编辑的安装不是一个选项。 有没有?
解决方法可能是构建一个轮子(直接使用您的构建后端)然后指向 pip 安装它
为什么该功能不能是可选的,所以它不会引起问题,但可以通过参数或类似的东西启用?
它可以。 恢复更改的原因是我们没有任何选择退出或获取更改反馈的期限。 我们确实有新的标志来帮助促进这一点(--use-feature 和--deprecated-feature),但现在必须有人在这种情况下重新实现/重新引入该功能。
从广义上讲,我认为我们想要在这里做的是:
解决方法可能是构建一个轮子(直接使用您的构建后端)然后指向 pip 安装它
我在想没有额外的构建步骤。 但我想我从一开始就不应该认为 Python 可以在没有 Makefile 等价物的情况下逃脱。
最有用的评论
旁白:没有。