Pipenv: Pipfile.lockからrequirements.txtを生成します

作成日 2019年01月31日  ·  25コメント  ·  ソース: pypa/pipenv

ロックせずに既存のPipfile.lockからrequirements.txtファイルを生成するにはどうすればよいですか?
pipenv lock -rを実行すると、既存のPipfile.lockが無視され、ロックプロセスが再度実行されます。

これには回避策があります。

$ pipenv sync
$ pipenv run pip freeze

私の特定の状況では、Dockerイメージを構築し、 Dockerfileで$ requirements.txtを使用しています。 requirements.txtを作成できるようにするためだけに、ホストマシン上に仮想環境を作成することは避けたいと思います。

最も参考になるコメント

あなたが実行することができます

pipenv run pip freeze > requirements.txt

全てのコメント25件

Pipenvはこれを行う方法を提供していません。pipfile-requirementsなどの他のpipfileユーティリティライブラリを探すことができます。

あなたが実行することができます

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ツール

笑、私はすでにそのライブラリについて言及しました。

私は個人的に、そのための専用のライブラリを持っているのが嫌いです。 また、チームメンバーがすでにjqまたはその他の汎用ツールをインストールしている可能性が高くなります。

あなたも実行することができます

 pipenv lock --requirements > requirements.txt

私が書いたように、それはあなたが期待するようには機能しません:

pipenv lock -rを実行すると、既存のPipfile.lockが無視され、ロックプロセスが再度実行されます。

つまり、更新を実行し、ディストリビューションを破壊する可能性があります。 requirements.txtを生成してDockerfileで使用し、Dockerイメージを構築するとします。 アプリケーションはローカルで機能しますが、 pipenv lock $を使用して$ requirements.txtを生成すると、要件が互換性のないバージョンまたは壊れたバージョンに更新される場合があります(ただし、まれなケースです)。 そして、イメージを実行する前にこれを知ることはできません。 したがって、 pipenv lockを実行した後、アプリを再度テストする必要があります。

jqを使用したくない場合は、最初の投稿で提案したpipenv syncのアプローチを使用することをお勧めします(これは更新されません)。

@Zebradil jqワンライナーアプローチは、 @frostming独自のpipfile-requirementsパッケージ(100行以上のPythonコード)よりもはるかに簡単です。これは、 jqを既にインストールしているため、他の依存関係はありません。必要です、それは素晴らしいです。

しかし、数回のgitコミットの後、 pipenv lock --requirementsの出力とjqPipfile.lockファイルを介して出力するものの違いに気づきました。

  • jqの出力には、 pipenv lock --rが常に最初の行として挿入するものとは対照的に、最初の行として-i https://pypi.org/simpleがありません。
  • jqの出力には、パッケージの注釈は含まれていません。 例: pipenv lock --r出力にはこの行appnope==0.1.0 ; sys_platform == 'darwin'がありますが、 jq出力ではappnope==0.1.0です。 別の例は、 pipenv lock -rpexpect==4.7.0 ; sys_platform != 'win32' $を生成するのに対し、 jqpexpect==4.7.0 $を生成しますが、これが重要かどうかはわかりません。
  • 要件ファイルのパッケージの順序は、2つの出力間で異なります。 jqは、おそらくPipfile.lockファイルのパッケージ順序を取ります。これは、常にアルファベットと文字長の昇順で並べ替えられます。たとえば、 flaskflask-sqlalchemyの前にあります。 flask-XXXXXパッケージに対して、 pipenv lock --rflask-sqlalchemy $の後ろに$ flask $を出力します。これは、 Pipfile.lockの順序とは異なります。 最小のgitdiffが生成されないため、これは大きな問題です。 これは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でさらにもう1つの最小限の依存関係のないスクリプトを作成しました。 また、Pipfileでソースがそのように定義されている場合は、env変数を拡張します。

誰かが見てみたい場合は、ここに残しておきます: 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:f4b2edfa0d226b70bd4ca31ea7e389325990283da23465d572ed1f70a7583041

これにより、 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ファイルに大文字と小文字が混在するパッケージ名が含まれている可能性があるためですが、Pipfileではpipenv install -r requirements.txtそれらを小文字にします。

Pipfile (ロックファイルではない)をrequirements.txtファイルに変換する場合の小さなPythonスクリプトを次に示します。

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を使用できます。

@frostmingpipfile.lockをサポートしていない他のツールで使用すると非常に便利だと思います。
pipenv lock -rの問題は、pipfile.lockが更新されるため、他のツールと一緒に決定論的なビルドを作成するために使用できないことです。 pipenv lock -r --ignore-pipfileのようなものが理想的です。

ハッシュを使用してPipfile.lockファイルからrequirements.txtを生成するさらに別のPythonスクリプトを次に示します。

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()

@Zebradilありがとう! あなたの解決策は本当に私のために働いた。

  • 最初にbrew install jqを使用して$ jqツールをインストールします
  • 次に、スクリプトを使用して、 Pipfile.lock requirements.txtを生成しました

これは--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

pip install --require-hashesが機能するように、ハッシュをPipfileからrequirements.txtにコピーするもの(たとえば、プラットフォームstrのようなものを指定)はありますか?

$ 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.

Pipenv.lock(またpoetry.lock)ファイルをrequirements.txt(rawrequirements.txtまたはpip-tools互換)に変換できるmicropipenvを使用できます。 https://github.com/thoth-station/micropipenv/#micropipenv-requirements--micropipenv-reqを参照してください

このページは役に立ちましたか?
0 / 5 - 0 評価