Pipenv: Создайте файл requirements.txt из Pipfile.lock.

Созданный на 31 янв. 2019  ·  25Комментарии  ·  Источник: pypa/pipenv

Как сгенерировать файл requirements.txt из существующего Pipfile.lock без блокировки?
Когда я запускаю pipenv lock -r , он игнорирует существующие Pipfile.lock и снова выполняет процесс блокировки.

Для этого есть обходной путь:

$ pipenv sync
$ pipenv run pip freeze

В моей конкретной ситуации я создаю образ докера и использую requirements.txt в Dockerfile . Я бы не хотел создавать виртуальную среду на хост-компьютере только для того, чтобы иметь возможность создавать requirements.txt .

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

Вы можете запустить

pipenv run pip freeze > requirements.txt

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

Pipenv не предоставляет для этого способа, вы можете искать другие служебные библиотеки pipfile, такие как pipfile-requirements

Вы можете запустить

pipenv run pip freeze > requirements.txt

Вы можете запустить

pipenv run pip freeze > requirements.txt

Это то, что я упомянул в качестве обходного пути в первом посте.

Но это работает, только если у вас синхронизирована среда pipenv (установлены все пакеты).
Извлечение зависимостей напрямую из Pipfile.lock мне удобнее:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

Сообщение блога
jq-инструмент

LOL, я уже упоминал эту библиотеку.

Лично мне не нравится иметь для этого специальную библиотеку. Кроме того, существует более высокая вероятность того, что член команды уже установил jq или какой-либо другой инструмент общего назначения.

ты даже можешь бежать

 pipenv lock --requirements > requirements.txt

Это не сработает так, как вы ожидаете, потому что, как я уже писал:

Когда я запускаю pipenv lock -r , он игнорирует существующий Pipfile.lock и снова выполняет процесс блокировки.

Другими словами, он выполняет обновление, которое потенциально может уничтожить дистрибутив. Представьте, вы генерируете requirements.txt , чтобы использовать его в Dockerfile для создания образа Docker. Локально ваше приложение работает, но когда вы генерируете requirements.txt с помощью pipenv lock , требования могут быть обновлены до несовместимых или просто сломанных версий (хотя, надеюсь, это редкий случай). И вы этого не узнаете до запуска образа. Итак, вам нужно снова протестировать приложение после запуска pipenv lock .

Если вы не хотите использовать jq , то лучше используйте подход, который я предложил в первом посте с pipenv sync (который не выполняет обновление).

@Zebradil, ваш подход jq oneliner намного проще, чем собственный пакет @frostming pipfile-requirements (100+ строк кода Python), поскольку я уже установил jq , никаких других зависимостей требуется, и это здорово.

Однако после нескольких коммитов git я заметил разницу между тем, что выводит pipenv lock --requirements , и тем, что jq подбирает через файл Pipfile.lock и распечатывает:

  • Вывод jq не содержит -i https://pypi.org/simple в качестве самой первой строки, в отличие от того, что pipenv lock --r всегда вставляется в качестве самой первой строки.
  • Вывод jq не включает аннотацию для пакетов. Например: вывод pipenv lock --r имеет эту строку appnope==0.1.0 ; sys_platform == 'darwin' , но в выводе jq это appnope==0.1.0 . Другой пример: pipenv lock -r генерирует pexpect==4.7.0 ; sys_platform != 'win32' , тогда как jq генерирует pexpect==4.7.0 , не уверен, имеет ли это значение или нет.
  • порядок пакетов файла требований отличается для двух выходных данных. jq , который предположительно принимает порядок пакетов в файле Pipfile.lock , который всегда сортируется по возрастанию алфавитов и длины символов, например, flask стоит перед flask-sqlalchemy или любые пакеты flask-XXXXX , тогда как pipenv lock --r выводит flask после flask-sqlalchemy , что отличается от порядка в Pipfile.lock . Это серьезное раздражение, потому что оно не генерирует минимальный git diff. Я бы посчитал, что это ошибка в pipenv .

Привет @ye , хорошее сравнение методов. Это может помочь людям выбрать правильное решение для их конкретной ситуации и избежать предостережений.

Да, как вы сказали, предлагаемый подход с jq имеет ограниченную функциональность. Его можно расширить, добавив аннотации и URL-адрес индекса пакета, но сейчас мне это не нужно.

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

Вы можете запустить

pipenv run pip freeze > requirements.txt

Это то, что я упомянул в качестве обходного пути в первом посте.

Но это работает, только если у вас синхронизирована среда pipenv (установлены все пакеты).
Извлечение зависимостей напрямую из Pipfile.lock мне удобнее:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

Сообщение блога
jq-инструмент

Привет,

Спасибо за ваше решение. Я столкнулся с той же проблемой, но мне также нужно определение источников, созданных pipenv lock -r , то есть: -i, --extra-index-url. Это потому, что я работаю с частными источниками.

@Zebradil , я думаю, ты упомянул об этом.

Поэтому я создал еще один минимальный скрипт без зависимостей на python, который включает эту функциональность. Он также расширяет env vars, если у вас есть источники, определенные таким образом в вашем Pipfile.

Если кто-то хочет взглянуть, я оставлю это здесь: https://gist.github.com/rcastill/dab85c234dd10fa7af56755116c75aee .

Если это поможет кому-то еще, вот как включить хэши в результаты:

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock

Это создает такие записи, как

paramiko==2.6.0 --hash=sha256:99f0179bdc176281d21961a003ffdb2ec369daac1a1007241f53374e376576cf --hash=sha256:f4b2edfa0d226b70bd4ca31ea7e389325709906158d570990283d5234

Что заставляет pip применять хэши.

Если вы хотите включить только те требования, которые были в исходном файле требований (при условии, что они уже были привязаны к определенной версии с помощью == ):

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock | grep --file=<(grep --only-matching --perl-regexp '^.*(?===)' requirements.txt | tr '[:upper:]' '[:lower:]') > new.txt && mv new.txt requirements.txt

tr необходим, потому что файлы requirements.txt могут содержать имена пакетов в смешанном регистре, но pipenv install -r requirements.txt в Pipfile пишут их строчными буквами.

Вот небольшой скрипт на Python на случай, если вы захотите превратить Pipfile (не файл блокировки) в файл requirements.txt.

import configparser


def main():
    parser = configparser.ConfigParser()
    parser.read("Pipfile")

    packages = "packages"
    with open("requirements.txt", "w") as f:
        for key in parser[packages]:
            value = parser[packages][key]
            f.write(key + value.replace("\"", "") + "\n")


if __name__ == "__main__":
    main()

@frostming Привет, я нашел https://github.com/frostming/pipfile-requirements полезным, но почему он не был интегрирован в pipenv?

@linusguan Инструмент существует для тех, кто не хочет устанавливать большую библиотеку pipenv, когда вы установили pipenv, вы можете использовать pipenv lock -r

@frostming Я считаю его весьма полезным для использования с другими инструментами, которые не поддерживают pipfile.lock.
Проблема с pipenv lock -r заключается в том, что он обновляет pipfile.lock, поэтому я не могу использовать его для создания детерминированной сборки вместе с другими инструментами. Что-то вроде pipenv lock -r --ignore-pipfile было бы идеально.

Вот еще один скрипт на Python для создания файла requirements.txt из файла Pipfile.lock с хэшами:

import os
import json

__dir__ = os.path.dirname(os.path.realpath(__file__))


def read_json_file(path):
    with open(path) as f:
        return json.load(f)


def main():
    root = read_json_file(os.path.join(__dir__, 'Pipfile.lock'))

    for name, pkg in root["default"].items():
        version = pkg["version"]
        sep = lambda i: "" if i == len(pkg["hashes"]) - 1 else " \\"
        hashes = [f'--hash={t}{sep(i)}' for i, t in enumerate(pkg["hashes"])]
        tail = '' if len(hashes) == 0 else f' {hashes[0]}'
        print(f'{name} {version}{tail}')
        for h in hashes[1:]:
            print(f'    {h}')


if __name__ == "__main__":
    main()

@Зебрадил Спасибо! Ваше решение действительно сработало для меня.

  • Сначала я устанавливаю инструмент jq , используя brew install jq
  • Затем использовал ваш скрипт для генерации requirements.txt из Pipfile.lock

Похоже, это можно решить с помощью флага --keep-outdated , или я ошибаюсь?

pipenv lock --keep-outdated -d -r > requirements.txt

PS это раздражающе многословный флаг, чтобы решить эту проблему

К сожалению , @jacobisaliveandwell флаг --keep-outdated появляется для обновления подзависимостей: https://github.com/pypa/pipenv/issues/3975

@paytonrules Это ошибка, но дух флага по-прежнему является ответом на эту проблему.

PS Не надо минусовать за это :-(

Сразу хочу отметить, что от заявленных обходных путей есть отличия:
pipenv run pip freeze возвращает имена пакетов с учетом регистра (например, PyYAML )
pipenv lock --requirements возвращает все имена пакетов в нижнем регистре (например, pyyaml )

@ Darkless012 , вы должны открыть еще один тикет, описывающий это, и сослаться на эту проблему как на связанную.

Чистый bash, только пакеты, ничего больше, на тот случай, если кто-то не может или не хочет ставить jq, на всякий случай кому-то поможет,

cat Pipfile.lock \
  | grep -B1 '"hashes"\|"version": ' \
  | grep -v '"markers": \|"hashes": ' \
  | grep ": {\|version" \
  | sed -e 's/: {$//g' \
  | tr '\n' ',' | tr -s ' ' ' ' \
  | sed -e 's/, "version": "//g;s/", "/ /g;s/"//g;s/,//g' \
  | tr ' ' '\n' \
| grep -v "^$" > requirements.txt

Есть ли что-нибудь, что также копирует хэши из Pipfile в requirements.txt (например, с учетом что-то вроде платформы str), чтобы pip install --require-hashes работало?

$ pip install --help
# ...
  --require-hashes            Require a hash to check each requirement against, for repeatable installs. This option is implied when any package in a
                              requirements file has a --hash option.

Вы можете использовать micropipenv, который может конвертировать файлы Pipenv.lock (также поэзия.lock) в требования.txt (необработанные требования.txt или совместимые с pip-tools). См. https://github.com/thoth-station/micropipenv/#micropipenv-requirements--micropipenv-req

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