Остановите сбой pip на одном пакете при установке с require.txt

138

Я устанавливаю пакеты из requirements.txt

pip install -r requirements.txt

requirements.txtФайл гласит:

Pillow
lxml
cssselect
jieba
beautifulsoup
nltk

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

Насколько я понимаю, pip install -r requirements.txtкоманда завершится ошибкой, если какой-либо из пакетов, перечисленных в списке, requirements.txtне удалось установить.

Есть ли аргумент, который я могу передать при запуске, pip install -r requirements.txtчтобы сказать ему установить то, что он может, и пропустить пакеты, которые он не может, или выйти, как только он увидит, что что-то не работает?

ЭМГ
источник
3
Удалите lxml из вашего файла requirements.txt
RickyA 07
1
Спасибо, это сработает в этом случае, но в целом есть ли способ обойти это? Или это нормально - просто запустить команду, увидеть, что она не удалась, а затем удалить список пакетов?
emh 07
5
Если пакет указан в requirements.txtнем, вероятно, требуется , поэтому имеет смысл, что pipэто не удастся, если пакет не может быть установлен. Если код все равно работает без этого пакета, то это вряд ли является обязательным требованием. Случайное удаление неудачных пакетов, requirements.txtпохоже, просто вызовет проблемы с отсутствующими зависимостями.
larsks 07
1
@larsks очень часто может иметь несколько файлов requirements.txt для одной среды разработки или пакета. Например, может быть один полный необязательных инструментов, которые можно использовать для улучшения среды модульного / интеграционного тестирования или профилирования производительности, но которые не являются строго обязательными. Вы по-прежнему хотите управлять версиями одного исходного файла, выражающего эти пакеты и любые закрепленные версии, и полагаться на тот же pip install -r <some file>рабочий процесс для стандартизации создания соответствующей среды.
ely
4
Учитывая это, кажется очень глухим предлагать, что pip не должен поддерживать какой-либо тип изящного отказа / необязательного пропуска, который печатает предупреждение, но устанавливает то, что может. Это очень распространенная потребность именно в таком типе установки на основе pip из файла требований.
ely

Ответы:

230

Запуск каждой строки с помощью pip installможет быть обходным путем.

cat requirements.txt | xargs -n 1 pip install

Примечание: -aпараметр недоступен в MacOS, поэтому старый кот более переносим.

MZD
источник
21
для Mac:cat requirements.txt | xargs -n 1 pip install
Walty Yeung
5
Пришлось сделать: cat requirements.txt | cut -f1 -d"#" | sed '/^\s*$/d' | xargs -n 1 pip installубрать что-нибудь в комментариях и избавиться от пустых строк.
Нарек
1
По крайней мере, в GNU xargsесть -aопция флага, которая позволяет xargsчитать аргументы из файла, так что это можно сделать как xargs -n 1 -a requirements.txt pip install. Предотвращает УУОК и чрезмерную сантехнику
Сергей Колодяжный
7
Для windows :)FOR /F %k in (requirements.txt) DO pip install %k
wcyn
Даже без -aфлага, рассмотрит < requirements.txt xargs -n 1 pip install, или если вам не нравится , перенаправление на фронте xargs -n 1 pip install < requirements.txt. :-)
torek
10

Это решение обрабатывает пустые строки, строки с пробелами, # строки комментариев, строки с пробелами и # строками комментариев в файле requirements.txt.

cat requirements.txt | sed -e '/^\s*#.*$/d' -e '/^\s*$/d' | xargs -n 1 pip install

Подсказка к этому ответу для магии sed.

рубль
источник
1
Работает красиво. Я использовал pip freezeвместо cat requirements.txt.
Vishal
5

Для Windows:

версия пункта> = 18

import sys
from pip._internal import main as pip_main

def install(package):
    pip_main(['install', package])

if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        for line in f:
            install(line)

версия пункта <18

import sys
import pip

def install(package):
    pip.main(['install', package])

if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        for line in f:
            install(line)
Этьен Протон
источник
'main' не является частью pip. Ошибка.
Pranzell
4

xargs работах решения , но могут иметь проблемы с переносимостью (BSD / GNU) и / или быть громоздкой , если у вас есть комментарии или пустые строки в файле требования.

Что касается варианта использования, в котором может потребоваться такое поведение, я использую, например, два отдельных файла требований, один из которых содержит только список основных зависимостей, которые необходимо всегда устанавливать, а другой файл с неосновными зависимостями, которые присутствуют в 90% случаев. не требуется для большинства сценариев использования. Это было бы эквивалентомRecommends раздела пакета debian.

Я использую следующий сценарий оболочки (требуется sed ) для установки дополнительных зависимостей :

#!/bin/sh

while read dependency; do
    dependency_stripped="$(echo "${dependency}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
    # Skip comments
    if [[ $dependency_stripped == \#* ]]; then
        continue
    # Skip blank lines
    elif [ -z "$dependency_stripped" ]; then
        continue
    else
        if pip install "$dependency_stripped"; then
            echo "$dependency_stripped is installed"
        else
            echo "Could not install $dependency_stripped, skipping"
        fi
    fi
done < recommends.txt
Лео Кавай
источник
0

Спасибо, Этьен Протон, за чехлы для окон.

Но после обновления до pip 18 пакет pip не раскрывает main для публики. Таким образом, вам может потребоваться изменить такой код.

 # This code install line by line a list of pip package 
 import sys
 from pip._internal import main as pip_main

 def install(package):
    pip_main(['install', package])

 if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        for line in f:
            install(line)
Jaeyoon Jeong
источник
-1

Для Windows:

import os
from pip.__main__ import _main as main

error_log = open('error_log.txt', 'w')

def install(package):
    try:
        main(['install'] + [str(package)])
    except Exception as e:
        error_log.write(str(e))

if __name__ == '__main__':
    f = open('requirements1.txt', 'r')
    for line in f:
        install(line)
    f.close()
    error_log.close()
  1. Создайте локальный каталог и поместите свой requirements.txt в него файл.
  2. Скопируйте приведенный выше код и сохраните его как файл Python в том же каталоге. Не забудьте использовать.py расширение, например,install_packages.py
  3. Запустите этот файл с помощью cmd: python install_packages.py
  4. Все упомянутые пакеты будут установлены за один присест без остановки. :)

Вы можете добавить другие параметры в функцию установки. Подобно: main(['install'] + [str(package)] + ['--update'])

Pranzell
источник