<p>pip установка каталога очень медленная</p>

Созданный на 16 дек. 2014  ·  74Комментарии  ·  Источник: pypa/pip

См. Https://github.com/pypa/pip/issues/2195#issuecomment -524606986 для краткого описания этой проблемы.


Я сомневаюсь, почему pip требуется 17 секунд для обработки локального каталога, который не находится на 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

Вероятно, он должен, по крайней мере, регистрировать все, что занимает так много времени, но, возможно, он даже не должен делать то, что делает.

Обратите внимание, что строка «Обработка» появляется сразу, и почти вся задержка, кажется, находится между этой строкой и следующей.

needs discussion enhancement

Самый полезный комментарий

Реализация PEP 517 решит эту проблему.

Рассказчик: не было.

Все 74 Комментарий

Он делает копию всего каталога, включая .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 ( 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/issues/2196

Теперь это намного быстрее, когда 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 составляет 177M из 270M для всего моего каталога pip .

См. Https://github.com/pypa/pip/pull/2535 , который ускоряет unpack_file_url счет создания и распаковки sdist.

Эту проблему следует открыть повторно, поскольку объединенный PR ничего не сделал (см. Gh-3219).

Есть ли прогресс по этому вопросу?

Нет, и не похоже, что окончательное решение появится в ближайшее время. PEP 516 или PEP 517 необходимо принять, прежде чем можно будет принять решение о том, правильно ли генерировать sdist first (я лично так не думаю).

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 - запустите prepublish для пакетов URL-адресов git

@rgommers Как насчет добавления файла .pipignore в список файлов и каталогов, которые следует игнорировать, например .gitignore вместо жесткого кодирования некоторых имен файлов / каталогов, таких как .git и .tox ?

Это не очень хорошая идея - ответственность за решение этой медлительности перекладывается на разработчика каждого пакета, который просто не работает.

Если он есть в npm, это должно быть хорошо :) - https://docs.npmjs.com/misc/developers#keeping -files-out-of-your-package

это также активно ломает такие вещи, как setuptools_scm, еще больше ^^ - pip install создание копии папки уже сильно ломает вещи

При чем тут setuptools_scm? Его следует запускать в действующем репо, а не в каком-либо исходном пакете .

Это не очень хорошая идея - ответственность за решение этой медлительности перекладывается на разработчика каждого пакета, который просто не работает.

Попросите .pipignore неявно включать .git, .hg и т. Д. С пустым .pipignore, подавляющим это.

@ piotr-dobrogost установка pip из исходного репозитория будет прервана в различных обстоятельствах, когда pip не копирует достаточно контекста - например, pypa / setuptools_scm # 138

Ранее мы делали игнорировать директории как .git и такие , и сломали вещи , как PBR и должны были вернуться к изменению.

@dstufft он по-прежнему ломает материал, если он находится в

Хм, если эта поломка была достаточно серьезной, то здесь нет простого способа исправить ситуацию. Думаю, он ждет одного из PEP сборки.

pbr, должно быть, делает что-то совершенно необоснованное, если он падает без .git dir, но что ж ....

интересно, есть ли в этом прогресс? Не только .git или любые .${scm} папки вызывают проблемы, гораздо хуже, если люди включают .vagrant/ вместе с исходным кодом.

наличие настраиваемого .pipignore действительно поможет облегчить боль.

Для другой точки данных; у нас есть смесь Python и Javascript в некоторых проектах, поскольку мы используем Sphinx для документирования наших проектов Javascript. Следовательно, pip также копирует очень большой каталог node_modules , что может быть очень медленным.

Поэтому мы бы проголосовали за вариант .pipignore поскольку наш вариант использования подчеркивает, что жестко заданные значения не обязательно будут достаточными для всех типов проектов.

Люди действительно хранят все виды мусора в дереве, помимо файла SCM.

У меня есть несколько больших имитаций (16 ГБ +), созданных кодом, который я храню в том же каталоге, что и исходный код пакета (как способ отслеживания различных проектов).

pip install . копирует их в мой / tmp. На плохом разделе действительно не хватает места, и pip выходит из строя из-за ошибки дискового пространства.

Если sdist не предполагается использовать, а .pipignore расширяет интерфейс, то как насчет повторного использования кода для синтаксического анализа файла MANIFEST.in / MANIFEST? В нем должны быть описаны все файлы, необходимые для установки.

Хорошим обходным решением является использование редактируемой установки ( pip install -e $DIR ).

Хорошим обходным решением является использование редактируемой установки (pip install -e $ DIR).

За исключением тестирования, это не проверяет, что будет использовать пользователь, устанавливающий пакет из pypi. (например, пакеты и модули, которые не были упакованы, по-прежнему будут доступны)

Надеюсь, об этом уже упоминалось ранее в этой ветке.

Лучшим обходным решением было бы создать sdist или колесо напрямую с помощью setup.py и установить сгенерированный артефакт с помощью pip. Таким образом, pip не будет копировать каталог (потому что у него есть файл для установки), и это точно такой же результат, как и с pip install . (начиная с pip 9), за вычетом копия каталога.

Ради бога, ребята, а можно это уже как-нибудь решить, пожалуйста? Я имею в виду, что, похоже, существует некоторый консенсус в отношении того, что такое поведение бессмысленно, но билет открыт уже три года, и решения нет. Я ненавижу вручную перемещать данные в мое дерево и из него, чтобы pip не зависал и не зависал в течение нескольких минут (мне нужно работать с общими файловыми системами).

Если нет единого мнения о том, как не нарушить существующую работу, может ли решение вроде .pipignore быть предоставлено в качестве подписки? Я не против прыгнуть через несколько обручей, чтобы это исправить.

@ andre-merzky, пожалуйста, успокойся.

Мы знаем об этой проблеме, но мы волонтерская организация с очень ограниченными ресурсами. И с практической точки зрения эта проблема просто не затрагивает достаточно серьезно наших пользователей, чтобы быть в списке приоритетов.

Со временем это будет исправлено (и более серьезная работа, которую мы пытаемся решить на данный момент, в частности PEP 517, вероятно, решит эту проблему как побочный эффект), но крик на добровольцев не поможет. Если вы считаете, что немедленное исправление критически важно, мы будем рады рассмотреть PR - но вы должны знать, что даже если вы поднимете PR и добьетесь его принятия, он не будет выпущен до PIP 10, и это релиз, в который мы хотели бы получить хотя бы часть той «большой работы», о которой я упоминал выше (это может не произойти снова из-за нехватки ресурсов добровольцев, но это наша цель). Таким образом, он может быть заменен до того, как он будет выпущен, но это не значит, что вы не можете создавать PR, это будет запасным вариантом, если более крупные планы не будут реализованы вовремя.

@pfmoore извините за тон,

Попробуй и это:

(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 . Это зависит от stdlib tempfile .

Реализация PEP 517 решит эту проблему.

Я сталкиваюсь с этим с последней версией pip для разработчиков - я думал, что поддержка PEP 517 была добавлена ​​в pip 19, так должно ли это все еще происходить?

В моем случае, поскольку я работаю над проектом (астропия), где у меня много пультов и веток, размер моего каталога .git составляет 1,8 ГБ, и копирование его во временный каталог занимает несколько минут. Похоже, что было бы разумнее сначала создать исходный код, а затем построить колесо оттуда, за кулисами.

Мы все еще очень сильно болеем из-за этой проблемы. Очень сложно сказать нашим пользователям, что они не могут хранить код и экспериментальные данные (которые имеют большой размер) в одном каталоге - это довольно нелогично. В наших собственных системах мы используем патч .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»: я давно помирился с «маршрутом go 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 копирует исходный каталог во временный каталог, чтобы гарантировать, что сборка не зависит от чего-то вне источников.
  • Способ, которым мы хотим решить эту проблему, состоит в том, чтобы изменить поведение pip, чтобы создать исходный дистрибутив в дереве, распаковать исходный дистрибутив во временный каталог и построить из него двоичный файл.

Теперь, следуя этому пути, мы также исправляем кучу других проблем юзабилити, связанных с строительной механикой pip для пользователей.

Я начал инициативный проект по рефакторингу логики сборки pip. Хотя я не буду заниматься этой проблемой в рамках своей работы по рефакторингу, я более чем готов помочь кому-то, кто достаточно склонен попытаться исправить эту проблему - исправление будет в значительной степени вовлечено в логику сборки pip, которая не Это не самый простой фрагмент кода, и могут быть сложные крайние случаи, которые мы замечаем только во время реализации.

О, и как обходной путь для этого, добавленный в # 6770, pip 19.3 будет исключать каталоги .nox и .tox при копировании. Это должно сократить время, необходимое для установки, для значительного числа пользователей.

Это не решает проблему для больших каталогов .git или build - это решит подход, который я разработал в своем комментарии выше. :)

Это не решает проблему для больших каталогов .git или build - это решит подход, который я разработал в своем комментарии выше. :)

Я знаю, что есть инструменты, которые полагаются на .git , но полагается ли кто-нибудь на копирование build ? Это было бы неплохо добавить в игнорируемые каталоги, с удовольствием отправим пиар, если вы согласны.

Это все еще изучается? Очень неприятно видеть, как несколько гигабайт игнорируемых git дампов отладочных данных копируются во время pip install .

Да, взгляните на связанные проблемы, например # 7555.

Эта проблема все еще сохраняется, потому что каталог, из которого я устанавливаю, может иметь 10 МБ кода Python, но затем много файлов данных json и .git .

Это должно быть решено с помощью # 7882 (создание локальных каталогов на месте).

Сейчас (за # 7951) мы опубликовали бета-версию pip, pip 20.1b1. В этот выпуск входит № 7882, в котором реализовано решение этой проблемы.

Надеюсь, участники этого выпуска помогут нам, протестировав бета-версию и проверив наличие новых ошибок. Мы хотели бы выявить и устранить любые потенциальные проблемы до основного выпуска 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».

Недавно у нас было долгое обсуждение того, что означает редактируемая установка, и я думаю, что мы действительно попали в место, которое больше похоже на machine local в том, что касается pip. Но pip не знает, где и как на локальном компьютере, и это задание серверной части сборки, которое определяет и обрабатывает это.

Можно попробовать «встроить в дерево» (аналогично «бэкэнд PEP 517 в дереве») или «встроить в исходный каталог»

Мой вопрос: почему эта функция не может быть необязательной, чтобы она не вызывала проблем, но могла быть включена аргументом или чем-то подобным?

Я пытаюсь обдумать обходные пути для этого, когда редактируемая установка не является вариантом. Есть ли?

Обходной путь может заключаться в том, чтобы построить колесо (напрямую используя ваш бэкэнд сборки), а затем указать pip для его установки.

почему эта функция не может быть необязательной, чтобы она не вызывала проблем, но могла быть активирована аргументом или чем-то подобным?

Оно может. Причина отмены изменения заключалась в том, что у нас не было отказа или периода для получения отзывов об изменении. У нас есть новые флаги, которые помогают облегчить это (--use-feature и --deprecated-feature), но сейчас кто-то должен заново реализовать / повторно ввести функциональность в этом контексте.

В целом, я думаю, что мы хотим здесь:

  • Добавьте параметр --use-feature = in-tree-build в качестве опции.
  • Измените значение по умолчанию в более позднем выпуске с --deprecated-feature = out-of-tree-build в качестве отказа + подтолкнув пользователей --use-feature = in-tree-build отказаться от него.
  • Отбросьте оба варианта в следующем выпуске.

Обходной путь может заключаться в том, чтобы построить колесо (напрямую используя ваш бэкэнд сборки), а затем указать pip для его установки.

Я думал без лишнего шага сборки. Но я думаю, мне никогда не следовало думать, что Python может обойтись без эквивалентов Makefile с самого начала.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги