Pipenv: 提案:Pythonライブラリプロジェクトの `pipenv`パターンとアンチパターン

作成日 2018年04月05日  ·  74コメント  ·  ソース: pypa/pipenv

mayaハッキング私はいくつかのレッスンを学び、Pythonライブラリでのpipenvの推奨される使用法について次の提案をしました。 他の人が提案をレビューすることを期待し、合意に達すると、(更新された)テキストがpipenvドキュメントになってしまう可能性があります。

Pythonライブラリプロジェクトのpipenvパターンとアンチパターン

編集
以下は、さまざまなPythonバージョンとOSで実行されることになっている一般的な(主にオープンソースの)Pythonライブラリに最適です。 厳密なエンタープライズ環境で開発されたライブラリは、ケースが異なる場合があります(とにかく、すべての問題のセクションを確認してください)。

編集の終わり

TL; DR :Pythonライブラリプロジェクトにpipenvファイルを追加すると、複雑さが増し、ライブラリのセキュリティに何も追加せずにエラーを隠すことができます。 このため、 PipfilePipfile.lock 、および.envをライブラリのソース管理から除外してください。

.gitignoreファイルに関係なく、 pipenvフルパワーます

PythonライブラリとPythonアプリケーション

Pythonライブラリとは、PythonのバージョンやOSが異なるさまざまなプラットフォームでの配布と使用を対象とした、通常setup.pyプロジェクトを意味します。

例としては、 mayarequestsflaskなどがあります。

反対側(Pythonライブラリではない)には、特定のPythonインタープリター、OSを対象とし、厳密に一貫した環境にデプロイされることが多いアプリケーションがあります。

pipfileは、 Pipfileとsetup.pyの違いをよく説明しています。

pipenv (デプロイメントツール)とは

pipenv、次のことができる

  • 仮想環境の展開に関する厳密な要件( Pipfile.lock )を定義する
  • これらの厳格な要件を再現可能な方法でさまざまなマシンに適用します

これは、アプリケーションをデプロイしたり、複数の開発者間で非常に一貫性のあるPython環境で開発したりする必要がある場合に役立ちます。

pipenvパッケージングツールを呼び出すことは、Pythonライブラリを作成すること、またはそれらの作成に深く関与することを期待している場合、pipenvは(ライブラリのローカル開発で)大いに役立ちますが、害を及ぼす可能性があります(CIテストでは、深く考えずに使用することがよくあります)。

間違ったコンテキストで「セキュリティ上の理由」を適用する

TL; DRpipenvは、 Pipfile.lockファイルに記述されている承認済みの具体的な依存関係。Pythonライブラリは抽象依存関係の定義のみが許可されています(したがって、 Pipfile.lockは提供できません)。

pipenvは、次の手順に従う展開シナリオで優れています。

  • 抽象依存関係を定義Pipfile介して)
  • それから具体的な依存関係を生成し、結果としてPipfile.lock
  • それらの具体的な依存関係を反映する(仮想)Python環境を作成します
  • テストを実行して、特定の環境が期待どおりに機能し、安全であることを確認します
  • 承認されたPython環境の定義として、テスト済みの「ゴールデン」 Pipfile.lockをリリースします
  • 他の人はpipenv syncを使用して、他の場所で「ゴールデン」 Pipfile.lockを適用し、同一のPython環境を取得できます。

Pythonライブラリの開発では、ライブラリが具体的な依存関係を定義してはならないため、このようなセキュリティを実現することはできません。 このルールに違反すると(したがって、Pythonライブラリによって具体的な依存関係を宣言しようとすると)、次のような問題が発生します。

  • 満足のいくバージョンの共有ライブラリを見つけるための問題(各厳密なパッケージは共有ライブラリの正確なバージョンを定義し、バージョンが異なり、一般的に受け入れられるバージョンを見つけることができない可能性が非常に高いです)
  • 具体的な依存関係は、Pythonのバージョン、OS、またはその他の環境マーカーに依存する可能性があり、異なるコンテキストでパッケージをインストールしようとすると、元の抽象的な依存関係で定義されたルールの一部を簡単に満たすことができません。

問題:壊れたsetup.py定義された依存関係を非表示にする

setup.pyは、 install_requires介してすべての抽象依存関係を定義します。

Pipfileこれらの依存関係も定義している場合、次のような問題を簡単に隠すことができます。

  • install_requires依存関係がありません
  • Pipfileは、依存関係の特定のルール(バージョン範囲など)を定義しますが、 install_requiresは定義しません。

それを防ぐには、次のルールに従ってください。

  • ライブラリで定義された依存関係はPipfile表示されてはなりません
  • Pipfile[packages]セクションは空であるか、ライブラリ自体への単一の依存関係のみを定義する必要があります。

問題:リポジトリ内のPipfile.lock

ライブラリリポジトリにPipfile.lock (通常は「セキュリティ上の理由」)を保持するのは間違っています。理由は次のとおりです。

  • 説明されている依存関係は、異なるPythonバージョンまたは別のOSでは無効である可能性があります
  • 開発者は、依存関係を追加/削除するときだけでなく、他のライブラリが更新されてライブラリ内で使用できるようになるときにも、ファイルを更新する必要があります。

それを防ぐには、次のことを行う必要があります。

  • リポジトリからPipfile.lockを削除し、 .gitignore追加します

問題: toxと競合する( usedevelop

tox.iniに次のようなcommandsセクションエントリが含まれている場合:

  • pipenv install
  • pipenv install --dev
  • pipenv lock

それはしばしば問題になります。理由は次のとおりです。

  • pipenv installはライブラリ自体のみをインストールし、 toxは(デフォルトで)それも実行します。 重複は別として、 Pipenvは1つのバリアント(およびtox.iniでしか表現できないため、 tox.iniusedevelop=Trueusedevelop=Falseも防止します。 tox.iniは、さまざまな環境での違いを許容します)。

それを防ぐには、次のことを行う必要があります。

問題: pipenvが失敗した場合、ビルドを壊す

pipenvは開発が進んでおり、状況はいつか壊れます。 このような問題でCIビルドが破損した場合は、 pipenvを使用せず、従来のツール(多くの場合少し成熟している)を使用することで防止できる障害が発生します。

それを防ぐには、次のことを行う必要があります。

  • pipenvをCIビルドスクリプト、 tox.iniまたは同様の場所に追加する前に、よく考えてください。 追加することでどのような価値が得られるか知っていますか? 既存のツールで仕事をすることができますか?
  • 「セキュリティ上の理由だけで」または「誰もが追加する」という理由で追加しないでください。

概要

Pythonライブラリの開発におけるpipenv役割に関する重要な質問は次のとおりです。

  • pipenv実際にもたらす価値 A: Virtualenv管理ツール。
  • pipenvするユースケースは何ですか? A: virtualenvを管理します。
  • ライブラリリポジトリに表示しますか? A:いいえ。

詳細とコツはほとんどありません。

pipenvはパッケージにセキュリティを追加しません

誰もがそれを行うという理由だけで、または追加のセキュリティを期待しているという理由だけで、それをプロジェクトにプッシュしないでください。 それはあなたを失望させるでしょう。

具体的な(そして承認された)依存関係を使用して保護することは、ライブラリを使用するアプリケーションの後のフェーズで行われます。

PipfilePipfile.lock 、および.envファイルをリポジトリから除外します

ファイルを.gitignore入れます。

Pipfileは、ほとんどまたはすべての要件がsetup.pyすでに定義されているため、以下に示すように簡単に再作成できます。 また、 .envファイルにはおそらく個人情報が含まれているため、共有することはできません。

これらのファイルをリポジトリから除外することで、適切でない状況でpipenvを使用するときにCIビルドで発生する可能性のあるすべての問題を防ぐことができます。

開発者のプライベートツールボックスとしてのpipenv

pipenvは、virtualenv管理ツールとしての開発者の作業を簡素化する可能性があります。

秘訣は、(プライベート) pipenv関連ファイルをすばやく再作成する方法を学ぶことです。例:

$ cd <project_repository>
$ # your library will bring the dependencies (via install_requires in setup.py)
$ pipenv install -e .   
$ # add more dev tools you preffer 
$ pipenv install --dev ipython pdbpp
$ # start hacking
$ pipenv shell
...

環境変数を設定するための便利な方法が必要な場合は、 .envファイルを使用してください。

注意:CIビルドにpipenv使用しないようにすると、作業が簡単になります。

トリック: setup.py機能を使用して、追加の依存関係を宣言します

setup.pyextras_requiresセクションを使用します。

from setuptools import setup

setup(
    name='mypackage',
    ....,
    install_requires=["jinja2", "simplejson"],
    extras_require={
        'tests': ['pytest', 'pyyaml'],
        'pg': ['psycopg2'],
    },
    ....
)

tests追加で宣言されたすべての依存関係をインストールするには:

$ pipenv install -e .[tests]

常にinstall_requires依存関係が含まれることに注意してください。

この方法では、依存関係をデフォルトセクションと開発セクションに分割することはできませんが、予想されるシナリオではこれは実際の問題ではありません。

Discussion Type

最も参考になるコメント

@ Moritz90 Pythonのメーリングリストのいくつかは、この議論を行うのに適した場所です。

pypa-devは、Pythonパッケージングとその周辺のエコシステムを中心とした議論にとって最も明確です。 同様の議論を投稿するのであれば、おそらくここから始めます。

python-ideasはアイデアについて話し合う場所であり、Pythonコミュニティ全体に対して非常に高い可視性を備えています。 これをPEPレベルにプッシュしたい場合にも、これは良い出発点になると思います(最終的にはそうなると思います)。

全てのコメント74件

これは非常に印象的です。コンパイルしてくれてありがとう。 間違いなく少し詳しくレビューします

/ cc @uranusjr @jtratner @ncoghlan

maya問題へのいくつかの参照:

  • kennethreitz / maya#138(リポジトリからRemovePipfile.lock)
  • kennethreitz / maya#139(tox.iniで実行されるpipenvをスキップ...)
  • kennethreitz / maya#145(setup.pyのpendulum>=1.0を修正:バージョンはPipfileにありましたが、setup.pyにありませんでした)
  • kennethreitz / maya#143( pipenv問題がTravisの実行全体をどのように壊したかを示すPR)
  • kennethreitz / maya#144(半公式のベストプラクティスに従ったPRリファクタリングpipenvの使用法)

私もこれが大好きです。 たぶん、これをPipenvのドキュメント、またはPythonPackagingユーザーガイドに追加する必要があり

上記のアドバイスの当然の結果は、「決定論的/再現可能なCIビルドを無視する」ように思われます。これは、非常に大きなアンチパターンとして私を襲います。

決定論を可能にする代替案として何を提案していますか?

@ tsiq-oliverc現時点では、決定論的ビルドがその役割を果たしており、アプリケーションがビルドされます。

Pythonライブラリの本当に決定論的なビルドを実行する次の試みを想像してみてください。

  • ビルドはPipfile.lock基づいている必要があります
  • 各実行コンテキスト(各PythonとOSバリアントの組み合わせ)は、 Pipfile定義されたライブラリ抽象依存関係の結果として異なるPipfile.lock持つ可能性があります
  • リポジトリは、リポジトリで定義された個別のPipfile.lockインスタンスを提供する必要があります。 CIビルド中にPipfile.lock自動的にビルドしても、決定論は追加されないことに注意してください

これは多くの余分な努力です。 そして、取得するのはライブラリです。これは異なるコンテキストでインストールされ(たとえば、1週間後に標準インストールでアップグレードされた依存関係が1つか2つ取得されます)、事実から何も取得されません。 Pipfile.lockを使用しました。現時点では廃止されています。

競合は、ライブラリが内部で厳密な依存関係を定義してはならないという事実です。

あなたが考えるなら、Pythonライブラリの決定論的なビルドを取得する別の方法があります-それを説明してください。

@ vlcinsky-ライブラリのコンシューマーが異なるバージョンの依存関係などを使用している場合、それは制御できません。 ですから、図書館のメンテナがそれを管理するための実行可能な方法がないことに同意します。

しかし、ここでの目標はおそらくはるかに小さな範囲です。 特に、図書館のメンテナの目標は次のようになります(ほぼ同等です)。

  1. CIを2回実行すると、同じ結果が得られることが保証されます(ネットワークの問題にもかかわらず!)。
  2. Dockerなどを実行することを意味する場合でも、CIで観察される動作をローカルで再作成(したがってデバッグ)できます。 ローカルで。
  3. 「私のライブラリは依存関係バージョンX、Y、Zで期待どおりに動作します」と自信を持って消費者に伝えることができます。

これらの3つのことのいずれかが当てはまらない場合、それは品質管理とは正反対だと私は思います。

そうです、PythonバリアントA、B、Cをコンシューマーにサポートすることを保証し、それらが1つのロックファイル(など)でカットされないほど動作が異なる場合は、3つのロックファイル(またはなんでもいい)。

しかし、私はそれが実際にどれほど簡単であるかを知るのに十分なほどPipenvを使用していません。

現在、CIシステムのいくつかのライブラリプロジェクトにもPipfile追加することを検討しています。

全社的なセキュリティガイドラインに準拠するには、依存関係のロック(+ハッシュ)が絶対に必要です。公式にサポートされているのは1つしかないため、現在、異なるPythonバージョンでテストする必要はありません。 また、pipenvがvirtualenvを含むローカル開発環境のセットアップを簡素化するという事実は素晴らしい副作用です。

そして、取得するのはライブラリです。これは異なるコンテキストでインストールされ(たとえば、1週間後に標準インストールでアップグレードされた依存関係が1つか2つ取得されます)、事実から何も取得されません。 Pipfile.lockを使用しました。現時点では廃止されています。

これは普遍的に真実ではありません。 エンタープライズソフトウェアの世界では、公式にサポートされている非常に特殊な環境がまだあり、依存関係のセキュリティの問題により、顧客が依存関係を自分で更新するのではなく、製品が更新されます。

(はい、ここではアプリケーションではなく、ライブラリについて話しています...)

@ Moritz90シナリオはエンタープライズ環境のPythonライブラリ用であり、 pipenvははるかに決定論的な環境であるため、役立つ場合があります。

私の説明は、 flaskrequestmayaなど、コンテキストがはるかに可変である一般的なPythonライブラリを対象としています。 mayaでいくつかの問題を修正しようとすると、多くの場合、 pipenv使用すると、実際の問題(通常は検出される問題を非表示にする)が発生し、多くの機能や付加価値が提供されないという学習に不満が生じました。価値。

決定論的なビルドを取得することは良いことですが、コストがかかります。 そして、間違って行われた場合、低品質の結果に対して追加料金を支払う可能性があります-これは私が防ぎたかったことです。

これは、ビルドを完全に決定論==で固定しない場合、デフォルトで複数のバージョンへのサポートを維持することを約束しているので、そのようにライブラリを設計する必要があります。 CIのビルドを壊す依存関係のアップグレードは、ライブラリのバグを公開するため、実際には良いことです。 (Pipenvによって管理される)完全に決定論的な依存関係はそれを覆い隠します。 あなたがそれを望むときに決定的であることができることはまだ有益です、それは一般的に最良ではありません。

@ uranusjr-もちろんです。 私は、欲求が「非決定論的ビルド」である場合、一番上のアドバイスが理にかなっているかもしれないことに同意します。 実際、これはほぼ論理的に同等であり、はるかに簡潔に述べることができます。「決定論的ビルドが必要ない場合は、決定論的ビルドを保証することを目的としたツール( pipenv )を使用しないでください。」 😄。

しかし、それは確かに一般的に望ましい目標ではありません。

@ tsiq-oliverc素晴らしいスコープ定義-焦点を絞ったディスカッションをサポートします。 もう1つの要件を追加します。CIの決定論は、テストされたライブラリ内で発生する可能性のある問題を隠してはなりません。

Pipenv.lockを使用し、それに基づいてvirtualenvを作成し、ライブラリのCIテストを実行すると、ライブラリが実行するはずの機能の一部、つまり適切な依存関係をインストールしました。 ライブラリがこの点で何らかの理由で壊れている場合-プレインストールされた環境はこの問題を隠します。

私には、決定論的な方法でCIを実行するよりも、ライブラリ内の問題を検出する方が重要であるように思われます。 両方を行う方法がある場合(たとえば、決定論をサポートする可能性のあるプライベートpypi indexの背後でテストを実行する場合)、問題はありませんが、競合がある場合は、優先順位があります。

誤解しないでください。非決定論的なビルドを実行する必要はありません。CIビルドを実行することを望んでいます。これにより、可能な限り多くの問題が検出されます。

@vlcinsky確かに、更新されたドキュメントにもそれが反映されていることを確認するために、私の経験を共有したかっただけです。 現在のドキュメントは、トレードオフを説明するのに非常に役立ちます。

ライブラリの場合、setup.pyのinstall_requiresを介して抽象依存関係を定義します。 [...]
アプリケーションの場合、依存関係とそれらをPipfile内のどこで取得するかを定義し、このファイルを使用してPipfile.lock内の具体的な依存関係のセットを更新します。 [...]
もちろん、Pipfileとpipenvは、開発環境またはテスト環境を定義するために使用できるため、ライブラリ開発者にとっては依然として有用です。
そしてもちろん、ライブラリとアプリケーションの区別がそれほど明確でないプロジェクトもあります。

(私の場合に当てはまる部分を強調表示しました。)

私はそれがそのようにとどまることを確認したいだけです。 あなたの元の投稿には、PyPIで公開される予定のオープンソースプロジェクトについて話しているという免責事項のない包括的なステートメントが多すぎると思います。

@ Moritz90私は完全に同意します。 私はその焦点を強調しようとしていましたが、それをさらに見やすくすることができます。

@ Moritz90あなたのコメントを反映した紹介文を追加しました。

@ vlcinsky-それは理にかなっています。 私はあなたが明示的に非決定的構築する必要はありませんが、私はそれはあなたが(すなわち時に上流の依存関係の更新の問題をキャッチするために)したいものに不可避的同等だと考えていることを理解しています。

大声で考えて、これらの2つの相反する目標を解決するための最良の方法は何ですか? 1つの可能性は、2フェーズのCIプロセスを持つことです。

  1. 決定論的フェーズ。 リポジトリ内のPipfile.lockを活用するため、完全に再現可能です。
  2. 非決定論的フェーズ。 pipenv updateを実行してからテストを実行し、最新のすべての依存関係を取得します(これは、基本的にロックファイルがない場合の動作と同じだと思いますか?)。

@ tsiq-oliverc決定論的なビルドを取得するには、次の設定を考えます。

  • pypiキャッシュジョブの構築:一度に実行して、何らかの形式のpypiインデックスキャッシュを生成します(ファイルのディレクトリまたは同様のものとして)
  • ライブラリテストジョブ:pypiキャッシュを使用しますが、 pipenvを回避します

pipenvを使用してインストールを行うことは、ライブラリ自体をインストールすることと似ていますが、作業を行うコードが異なるため、明らかに異なります。

pypiキャッシュジョブを構築する

$ git clone <repo_url> <project_dir>
$ cd <project_dir>
$ pip install pipenv
$ $ # clean pypi cache and make it ready to cache somehow - not described here
$ pipenv install -e .[test]
$ # if we need extra testing packages in pipenv
$ pipenv install <extra_test_packages>
$ # record current requirements expressed in `Pipfile.lock`
$ pipenv lock
$ # if needed, record the `Pipfile.lock` somewhere

そのような仕事の成果は次のとおりです。

  • 記録された依存関係としてのPipfile.lock (開発者が環境を簡単に再現するのに役立つ場合があります)
  • 事前入力されたローカルpypiキャッシュ

ライブラリテストジョブ

フェーズがあります:

  • ローカルのpypiキャッシュのみを使用して、 toxpipなどを強制するように環境を構成します
  • CIテストを実行します( pipenv使用

私たちが得るもの

  • ライブラリは決定論的環境でテストされます
  • ライブラリは以下を含めてテストされます。 それはそれ自身でそれ自身をインストールする能力です
  • Pipfile.lockは、ライブラリのインストールに使用されたpypiパッケージを記録します。 開発者サイトで環境を再現するために使用できます。
  • (おそらく外部の)pypiでアップグレードされたパッケージへの適応は簡単で( "build pypi cache jobを再実行)、制御された方法で実行されます(pypiの内容はハッシュを含めて記録されます)

もう1つの利点は、この設定では、開発者がPipfileまたはPipfile.lock維持する必要がないことです。 また、異なるコンテキストでのテストの実行は常に同じです( Pipfile.lockは常に特定のコンテキストで再構築されます)。

まだ足りないもの(そしてできること)

pypiキャッシュは、いくつかの調査が必要な部分です。 おそらく、単純なディレクトリで十分であり、おそらくpipenvはすでにそれを支援する準備ができています。 たぶん、問題#1731は欠けている部分です。

依存関係の解決を行うパッケージとして、私たち自身のテストの多くは決定論的なビルドに依存しています。つまり、既知のものを取得し、解決されたグラフを期待しています。 これにはpytest-pypiを使用します。

このトピックに関する活発な議論が大好きです。 ニュアンスは重要だと思います。ピン留めされていない依存関係だけでなく、既知の依存関係に対しても常にテストする必要があります。

既知の依存関係と固定されていない依存関係に対して常にテストする必要があります

私はこの提案を2番目にしています。 新しいマイナー/バグ修正バージョンも同様に機能することを確認することに加えて、再現可能なビルドのために常に明示的な「既知の良好な状態」を持ち、更新によって何かが壊れた場合のデバッグを簡素化することをお勧めします。

(私の個人的な意見では、理想的な状況は、パッケージマネージャーがデフォルトで最新のマイナーバージョンをインストールして、ライブラリがテストされた具体的な依存関係バージョンを常に指定できるようにすることですが、それは非常に物議を醸す意見であり、すべての人が必要ですsemverをフォローします。)

@ Moritz90 @techalchemy @uranusjr @ tsiq-oliverc

これが前の議論からの私の要約です。

特定の問題と提案された解決策

多くの実行コンテキスト-誰がPipfile.lockファイルを維持するのですか?

サポートされている各OSとPythonインタープリターは、可能な実行コンテキストのマトリックスに貢献します。

例:Flaskサポート(少なくともリポジトリに表示されるCIのもの):

  • OS Windows(python2.7およびPython3.6)
  • Linux(python 2.7、3.4、3.5、3.6、nightly、pypi)
  • OSX(py-他にもバージョンがあるかどうかわからない)

それは異なるかもしれない9つの異なる実行コンテキストを作ります。

各実行コンテキストには、異なるPipfile.lockます。

誰がそれらを維持しますか?

オプションは次のとおりです。

  • 開発者に手動でそれをさせましょう(方法はありません)
  • メインの開発プラットフォーム用にPipfile.lockを1つだけ維持します(どのプラットフォームが無視されるのを楽しんでいますか?)
  • CIを介した作成の自動化(はい)

提案:CIにpipenv install -e .ファイルを生成させます。 自動ビルドの結果として開発者が適切なPipfile.lockを選択できるように、リポジトリに含めないでください。

開発者は予測可能な環境を必要としています

pypiへの依存関係の変更によって引き起こされる可能性がある問題を修正する場合、開発者は失敗したテストから環境を再現するための簡単な手段を必要とする場合があります。

提案:

  • 多くのパッケージでは、pypiの依存関係の変更は非常にまれであるため、実際の問題ではありません。
  • 環境を独自に修正するために、開発者はPipfile.lockpipenv install -e .その後にpipenv lockます。
  • 失敗したテストから環境を複製するために、開発者は失敗したテストからPipfile.lockを選びます。
  • todo:例、 tox.ini Pipfile.lockを適用する方法を示します。

CIは壊れたsetup.py明らかにする必要があります

ライブラリsetup.pyが壊れている可能性があり( install_requires依存関係がない、バージョン指定子がないなど)、CIテストでそのような問題を隠してはなりません(省略された依存関係を独自にプレインストールすることによって)。

提案:

  • pipenv install -e .を信頼して、プレーンインストールと同じ結果を提供します(現在、いくつかの問題があります)。
  • プレーンインストールテスト( pipenv )を実行し、結果のpip freeze出力がpipenvによってインストールされたもののサブセットであることを比較します。

更新されたpypiの依存関係は物事を壊す可能性があり、CIはそのような追跡を検出する必要があります

一部の依存関係の更新は、それを使用してライブラリを壊す可能性があります。 CIは、そのような問題の障害を検出するものとします。

提案:

  • 固定されていないバージョンに対して少なくとも1つのテストを実行する必要があります
  • CIが常に新しいPipfile.lock生成する場合、これは問題ではありません(とにかく固定されていないモードで実行するため)

さまざまなライブラリタイプのCIモード

提案されたすべてのモードで、リポジトリにpipenvファイルを保持しないようにして、開発者がこの非常に複雑なものを維持するのを防ぎました(自動化!!!)。

私の元のテキストとは対照的に、2番目と3番目のモードはCIスクリプトでpipenvを使用します。

モード:実行、フォレスト、実行!

頻繁に変更されない、依存関係の数が少ない単純なパッケージ。

pipenv時代の前と同じように実行し、物事をシンプルに保ちます。

依存関係によって問題が発生するまれなケースは簡単に修正でき、CIをより複雑にすることを正当化するものではありません。

モード:生成して封印する

CIテストを実行するたびに、現在使用されている環境を完全に説明する新しいPipfile.lockを生成します。

Pipfile.lockはCIアーティファクトになります。

問題が発生した場合、開発者は壊れたビルドからPipfile.lockを選択し、ローカルに適用して、テストと修正を行うことができます。

誰かがデプロイしたい場合Pipfile.lock 、最後に成功したビルドの

モード:氷河期

依存関係の変更が実際の問題である場合、CIはPipfile.lock一度に作成し、特定の期間(1か月?)使用し続けます。

これにより、少なくとも2つの異なるジョブが必要になるため(1つはPipfile.lockを生成し、もう1つはそれを適用してテストで使用する)、CIのセットアップがより困難になります。

警告: Pipfile.lockも現時点で更新する必要があり、 setup.pyは依存関係を変更します。

Ice Ageでは、フリーズ状態を無視し、固定されていないバージョンをチェックするリスタイプのテストであるScratが必要であることに注意してください。

閉会の辞

見てのとおり、決定論と複雑さはモードごとに大きくなります。

私の提案は次のようになります。

  • 単純に開始します(「実行、フォレスト、実行」)。 効率とスピードが得られます。
  • 依存関係の変更により状況が複雑になりすぎる場合は、「生成して封印する」に進んでください。 ローカル環境で再現性が得られます。
  • 物事が本当に悪い場合は、「氷河期」モードに移動します。 あなたは(一時的な)決定論を獲得します。

すべての利益には何かがかかります。

ここでの目標がドキュメントのアドバイスを更新することである場合、正直なところ、「選択の余地がなくなるまで、デフォルトでベストプラクティス(再現性のあるビルド)に従う」とは劇的に異なることを言うのは無責任だと感じます。

@vlcinsky 「モード:生成して封印する」という見出しの下で、最後に成功したPipfile.lockは、たとえばJenkinsアーティファクトとして宣言するなどして、常に保持する必要があることに言及するのが理にかなっています。 この変更により、ほとんどのプロジェクトでそのセットアップを推奨するのは問題ありません。 @ tsiq-olivercのように、最初のモードはお勧めしません。

考えれば考えるほど、このドキュメントは、ライブラリを開発している場合でも、CIビルドにpipenvを使用することが優れたアイデアである理由に関するセクションになると思います。

@ tsiq-oliverc一般的なPythonパッケージの大部分は、「実行、フォレスト、実行」モードです。 toxpytestを導入することで、これらのパッケージのいくつかを支援しました。これは、特定のパッケージ品質に貢献すると感じ、非常に明確なアイデアを持っていたためです。

今、別の素晴らしいツールがあり、一般的なPythonプロジェクトでpipenv適切に使用して、その品質に貢献する方法を考えています。 私は正当化され、従うのが簡単な1つか2つのうまく機能するレシピを見つけたいと思っています。

Flaskプロジェクトに何を言いますか?

  1. 選択の余地がなくなるまで、デフォルトでベストプラクティス(再現性のあるビルド)に従いますか?
  2. 9つのPipfile.lockファイルを追加し、それらを更新するためのポリシーを設定しますか?
  3. TravisとAppveyorのCIスクリプトをリファクタリングして、Ice Ageモードに続いて2フェーズで動作するようにしますか?
  4. TravisとAppveyorのCIスクリプトを変更して、誰かが自分のコンピューターで失敗したテストを再現する必要がある場合に、 Pipfile.lockアーティファクトを生成しますか?
  5. 「Flaskに感謝します」以外のコメントはありません。

目標は、機能的な働き方を見つけることです。 それがドキュメントで終わっている場合は、問題ありません。

@vlcinsky (1)と(4)がそのようなプロジェクトの推奨事項になるはずです。 既存のPipfile.lockがないと、ビルドで使用されているバージョンを事前に知ることはできませんが(企業環境以外では問題ありません)、ロックファイルを生成してアーカイブすると、再現可能な結果が得られます。ビルド中。

編集:私の推奨のtl; drバージョンは次のようになります:

  • ライブラリまたはアプリケーションのどちらを開発しているかに関係なく、ビルドが再現可能であることを常に確認してください。 pipenvは、この目標を達成するのに役立ちます。
  • アプリケーションを開発している場合は、リポジトリにPipfile.lockをコミットし、それをデプロイに使用します。 (これはすでに既存のドキュメントでカバーされています。)
  • オープンソースライブラリを開発している場合は、CIビルドでオンザフライでPipfile.lockを生成し、後で使用できるようにアーカイブします。
  • ライブラリを開発していて、制限のある企業環境で作業している場合は、適切な数のロックファイルを維持し、CIビルドでそれらを使用します。

(もちろん、実際のドキュメントにはもう少し詳細と例が必要です。)

@ Moritz90あなたが提案したように「生成して封印」を変更しました。

Re(1):言うのは簡単で、より具体的にしないと実行できません。

Re(4):はい、「生成して封印する」が最も実行可能なモードだと思います。 しかし、フラスコの場合、私はあえてしません(少なくとも現時点では)。

エンタープライズ環境での既存のPipfile.lock再作成:(半)手動または自動で、何らかの方法で作成する必要があります。 企業環境では、パブリックpypiから直接インストールするのではなく、承認されたパッケージのみを提供するプライベートpypiを使用します( devpi-serverは、複数のインデックス、公開されたパッケージの制御されたボラティリティ、外部の承認など、優れたサービスを提供します)パッケージなど) Pipfile.lockを構築するプロセスがそのような環境で実行される場合、承認されたものしか使用できないため、新しいバージョンがそこに表示される場合は、誰かが立ち上がって承認する必要があります。 次のCIビルドは、問題が発生しないことをテストします。 また、 pipenv checkすると、セキュリティ問題のテストも自動化できます。

このようなワークフローは、誰かが(半)手動で作成するよりも安全だと思います。 しかし、エンタープライズ環境に関する私の知識は非常に限られています。

こんにちはpipenvチーム。 私はこのテキストで述べられていることの多くを共有しています。これは、ライブラリを開発するときに、開発者がPipfile / pipenvの制限をよりよく理解するのに役立ちます。 このテキストまたはこのテキストの一部が公式のpipenvドキュメントに統合されていることを確認したいと思います。

私は私が議論したい次の修正を持っています:

完全に再利用可能で、内部pypiで公開されている、内部pythonパッケージの場合、および私自身のpythonパッケージ(例: cfgtreetxrwlockpipenv-to-requirements )の場合でも、一部の人がすでに知っている、または使用している可能性のあるパッケージを使用します、これらの詳細を抽象化し、Python開発者の生活を楽にします:PBR。
PBRは基本的に、配布パッケージのルートフォルダーにあるrequirements.txt読み取り、それをsetup.pyinstall_requiresに挿入します。 開発者requirements.txt 、緩い依存関係宣言を使用してPipfileのサポートがPBR内に正式に統合されるまで、 Pipfileからrequirements.txtを自動的に生成するpipenv-to-requirementsを使用して、両方が同期され、両方がコミットされるようにする必要があります。ソースで、配布パッケージがビルドされた後、PBRは正しくインジェクションを行います。 pipenvを使用してこのrequirements.txtを生成できると思います

私はPBR用のPipfileのサポートに取り組んでいるので、 Pipfile (ロックファイルではなく)を読み取って、 requirements.txtと同じようにinstall_requires挿入できます。 requirements.txt

他の同様のパッケージが存在するかどうかはわかりません。なぜなら、それは人々が望まないかもしれない他のこともするからです(git履歴からのバージョン、AUTHORSとChangLogの自動生成)。

しかし、最終的には、Pythonライブラリのバージョン管理を作成、保守、および処理する方が非常に簡単だと実感しています。この経験を共有しないのは悲しいことです。 私はそれを私の会社で最新のPythonライブラリを書くための「推奨される」方法として宣伝しています。

ライブラリとpipenvに関するすべての問題を「ごまかす」ようなものだと私は偵察しますが、最終的には作業が完了し、開発者はこれまでのところ喜んで使用しています。 私が社内の新しいPython開発者に提供しているPythonトレーニングの一環として、最初にinstall_requires手動で管理するPythonライブラリを作成し、次にPBRに切り替えて簡単になることを確認します(率直に言って、私はpbrのセマンティックコミット機能のファンであり、適切なsemverバージョンタグを自動的に作成します)。

ライブラリ専用のファイルを使用してライブラリの依存関係を宣言する理由の一部は、readthedocsやpyupなどのツールを使用できるようにするためです(アプリケーションにリンクしたときにpyupがより多くの意味を持っている場合でも)。

私は必ずしもこのメソッドをPythonパッケージを実行する「標準」の方法として宣伝したくはありません。実際には「OpenStack」の方法ですが、私の経験を共有したいと思います。他の人が同様または矛盾した経験を持っている場合は、それらを聞いて、私の視点を更新して幸せです。

チーム、ドキュメントの一種の「コミュニティ」セクションについてどう思いますか? 私のようなユーザーが、必ずしもpipenvチームの完全な承認なしに、pipenvの使用方法に関する彼の経験を共有できるようにするには?

PS:このスレッドを汚したくない場合は、これを専用の問題に移動できます

@vlcinsky (1)は非常に簡単に実行できます。

代わりにあなたが意味しているのは、この基本的な戦略がもはや十分でなくなったら、具体的なアドバイスを与えることは不可能だということだと思います。 それは確かに真実ですが、それは特定の問題がケースバイケースでおそらく異なるためです。

言い換えると、ソリューションは、CIワークフローに提供する追加の保証によって異なります。

@gsemetあなたは何を知っていますか? 過去2年間に作成されたすべてのPythonパッケージはpbr基づいています-それは本当に素晴らしいです。 そして、私はできる限りpbrでPipfileをサポートしようとするあなたの試みに従います(親指を立てる、投票するなど)。

この問題(一般的なPythonライブラリのpipenvパターンとアンチパターンの検索)の場合、次の2つの理由で意図的にpbrを省略しました。

  • それは概念的な議論をより複雑にするでしょう
  • 他の理由でpbrが気に入らない人もいます(あなたが言ったように)そしてそれはおそらく議論を回避するでしょう

一方で、pbr愛好家のためのあなたのレシピを本当に楽しみにしています。 読みます。

@ tsiq-olivercあなたは釘を打ちました:あなたのロックファイルをあなたのリポジトリに入れてください

これはまさに私がこの問題を始める動機となった問題です。 この問題の冒頭を読み直すと、 Pipfile.lock追加するとCIテストが失敗する可能性があるいくつかのケースの説明が見つかります(ビルドの実行を中断するか、問題を非表示にするか、そうでなければ検出されるか、間違った依存関係をインストールします)与えられたコンテキストに対して...)。

これが適切に行われているリポジトリ(一般的なPythonライブラリ)を見せていただければ幸いです。 または、どのようなリスクがあるのか​​、またはどのようなことが未完成であるのかを示します。

いいね ! 私もこのcookiecutterを維持

@vlcinskyそうですね、具体的な問題を列挙して解決策を見つけましょう😄(Pipenvを使用する高品質のライブラリは知りませんが、それは主に私が調べていないためです)。

私が知る限り、これらはあなたの元の投稿の特定の症状です:

  • 壊れたsetup.pyの依存関係を非表示にします。 これは問題ではないように聞こえます- pipenv install -e . 、そうですか?
  • 依存関係は、Pythonのバージョンが異なる場合や別のOSでは無効になる可能性があります。 これ問題になる実際に問題となっている場所の具体例を教えてください。 (ロックファイルのコンテキストで)
  • 開発者は更新を余儀なくされます...他のライブラリが更新され、ライブラリ内で使用できる場合があります。 彼らはそうすることを強制されていません。 ライブラリが依存関係のバージョンnではなくバージョンn + 1に対して機能することを保証したい場合は、これを行います。 しかし、私はすでに両方の長所を提供する代替案を提案していることに注意してください。
  • トックスとの競争。 Toxについては何も知りません。 しかし、はい、2つのツールを同時に使用して依存関係を管理することは、災害のレシピのように聞こえます。 その特定のタスクに優れている方を使用すると思います。
  • Pipenvは失敗します。 これは別の問題ではないように聞こえます-Pipenvのバージョンを固定するだけです(DockerイメージやPipのバージョンなどを固定するのと同じように、これが現在のソリューションです)。

@ tsiq-oliverc言わなければならないことですが、あなたのコメントは私にインスピレーションを与え、提案されたソリューションのより高いレベルの再現性に貢献したことを私は知っています。

以下は、再現性を確保するためにロックファイル( Pipfile.lock )をリポジトリに配置するという提案に関連しています。

壊れたsetup.pyの依存関係を非表示にします。pipenv install -e .は私が提案したものに従いますが、これはPipfile.lock使用法ではなく、(再)作成する方法であることに注意してください。 誰かがPipenv.lockを保持し、パッケージをインストールする前にそれを使用してvirtualenvを作成する場合、問題が存在します。

re依存関係は、Pythonのバージョンが異なる場合や別のOSでは無効になる可能性があります。 多くの例があります。Python2.7用にインストールされたdoit 、新しいバージョンがPython 2.xのサポートを終了したため、古いバージョンである必要があります。 watchdog依存関係には、プラットフォームに依存するライブラリが必要です。Linuxではinotify、Windowsでは他の何か、OSXでは他の何かです。 私の以前のクライアントは「これは決して起こらない」と言っていましたが、状況の50%で2週間以内に起こりました。 これはCIスクリプトのベストプラクティスではありません。

re開発者は更新を余儀なくされています..15人の寄稿Pipfile.lock再生成を忘れがちです。 たとえば、 mayaパッケージでは、新しい依存関係がsetup.pyに追加されたため、 Pipfile.lockを再生成するように求められました。 それは必要でしたか? 正しく更新しましたか? サポートされているすべての実行コンテキストに対して更新しましたか? 答えはノー、わからない、ノーです。 とにかく、あなたの提案に感謝します(それはあなたのコメントの隣に記述された解決策のために私にインスピレーションを与えました)。

re toxとの競合:Toxを使用すると、複数のvirtualenvを作成し、それらの中でテストを実行することを自動化できます。 通常のtox.iniは、Python 2.7、3.4、3.5、3.6、およびその他の必要な仮想環境を定義し、そこにパッケージをインストールしてテストスイートを実行できるようにします。 本格的なテスターのパワーツールとして確立されています。 pipenvはこの目的のためのツールではありませんが、必要なもののインストールを妨げる可能性があります。 ある意味で、私はあなたのアドバイスに従い、可能な場合はpipenvよりも優れたツール(tox)を使用することを提案しました。

rePipenvは失敗します。 これは本当に残念です。 ローカルホストで正常に実行されるCIテスト(toxベース)がありましたが、Travis経由で実行すると、 pipenv問題が原因で失敗しました。 今すぐ使用したい場合は、修正がリリースされるまでピン留めは役に立ちません。 しかし、これはそれがどうなるかです-私は待ちます。

私の元の投稿の一部は、見た目どおりに更新する必要があることに注意してください。CIスクリプトでpipenvを使用すると、正当な場所になります(後で使用できるようにvirtualenv構成を「封印」します)。

@ tsiq-oliverc最初は「既知の良い」バージョンと最新バージョンの両方に対してテストするというあなたの提案が好きでしたが、考えれば考えるほど努力を正当化するのはますます難しくなっています。 両方ではなく、どちらか一方を行うことを決定する必要があると思います。

唯一得られるのは、障害の原因が依存関係の更新なのかコードの変更なのかがすぐにわかるということです。 ただし、個別のコミットを行うか(ロックされた依存関係を手動で更新する場合)、ビルドが成功したときに生成された最新のロックファイルでバグを再現しようとする(常に最新バージョンを使用する場合)ことで、同じことを実現できます。 そして、制限された環境では、とにかく「ただ更新」することはできません...

@vlcinsky環境間の違いについてのあなたの一般的なポイントに同意しますが、「構成ごとに1つのロックファイル」という議論は私にはストローマンのように聞こえます。 実際には、少なくともいくつかの環境間でロックファイルを共有することができます。

まだ誰も答えられていない残りの未解決の質問の1つは、両方が異なる環境でテストし、依存関係をロックする必要がある場合にどのように対処するかです。 toxについては、それが存在すること以外は何も知らないことを認めなければなりませんが、 toxpipenv間に何らかの接着剤が必要なようです。それはどういうわけかこの問題を解決します。

@ Moritz90

ストローマンに会う

ストローマンとして機能するPipfile.lockバリエーションが多すぎることについて(他の人を私のフィールドから遠ざけるため):

フラスコ

私はflaskプロジェクト(非常に成熟していると考えています)を取り、toxテストを実行しました:

ここに、テストされたバリアントのリストが表示されます(Linuxではローカルで、WindowsとOSXは同じテストセットを実行しますが、環境が異なる可能性があるため、3を掛けます)。

1つのOSで16の異なるテストが実行され、そのうち5つはインストールされていないため失敗し(問題ありません)、1つはドキュメントのビルドを処理し(重要なライブラリが必要)、もう1つはカバレッジ(インポート可能なライブラリも必要)です。 )::

  coverage-report: commands succeeded
  docs-html: commands succeeded
  py27-devel: commands succeeded
  py27-lowest: commands succeeded
  py27-simplejson: commands succeeded
  py27: commands succeeded
  py35: commands succeeded
  py36-devel: commands succeeded
  py36-lowest: commands succeeded
  py36-simplejson: commands succeeded
  py36: commands succeeded
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy-devel: InterpreterNotFound: pypy
ERROR:   pypy-lowest: InterpreterNotFound: pypy
ERROR:   pypy-simplejson: InterpreterNotFound: pypy
ERROR:   pypy: InterpreterNotFound: pypy

作成されたvirtualenvごとに、 pip freeze > {venv_name}.txt requirements.txtファイルを作成しました

次に、ファイルのハッシュを計算し、ハッシュ値に従ってソートして、すべて同じものをグループ化します。 ここにストローマンが来ます:

b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py35.txt
b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py36.txt
cdf69aa2a87ffd0291ea65265a7714cc8c417805d613701af7b22c8ff2b5c0e4  py27-devel.txt
dfe27df6451f10a825f4a82dfe5bd58bd91c7e515240e1b102ffe46b4c358cdf  py36-simplejson.txt
e48cd24ea944fc9d8472d989ef0094bf42eb55cc28d7b59ee00ddcbee66ea69f  py36-lowest.txt
f8c745d16a20390873d146ccb50cf5689deb01aad6d157b77be203b407e6195d  py36-devel.txt
053e107ac856bc8845a1c8095aff6737dfb5d7718b081432f7a67f2125dc87ef  docs-html.txt
45b90aa0885182b883b16cb61091f754b2d889036c94eae0f49953aa6435ece5  py27-simplejson.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
564580dad87c793c207a7cc6692554133e21a65fd4dd6fc964e5f819f9ab249c  py27.txt
8b8ff4633af0897652630903ba7155feee543a823e09ced63a14959b653a7340  py27-lowest.txt

怖いですよね? すべてのテストから、2つだけが同じ凍結された依存関係を共有します。

これは、優れたテストスイートを備えた一般的なPythonライブラリの現実です。 これはおそらく、エンタープライズ環境でテストされたPythonライブラリとはまったく異なるものであることを認めるでしょう。

Jinja2

jinja2チェックします。これは、はるかに単純な獣のようです。

  coverage-report: commands succeeded
  py26: commands succeeded
  py27: commands succeeded
  py33: commands succeeded
  py35: commands succeeded
  py36: commands succeeded
ERROR:   docs-html: commands failed
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy: InterpreterNotFound: pypy

チェックサムを見て、py27.txtとpy26.txtが異なることに驚いています。

047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py26.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py33.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py35.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py36.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
743ad9e4b59d19e97284e9a5be7839e39e5c46f0b9653c39ef8ca89c7b0bc417  py27.txt

@vlcinskyそれは確かに怖いです。 Flaskが特別な場合なのか、それとも実際にそれが標準なのか疑問に思いますが、あなたは間違いなく私が間違っていることを証明しました。

私は今、Pythonライブラリがいつか同じ問題に悩まされることはなく、違いがそこでより管理しやすくなることを望んでいます。

@ Moritz90内部ライブラリは完全に異なるオーディエンスにサービスを提供しているため、実行コンテキストをはるかに狭く保つことができます。

一般的なPythonライブラリは、多くの場合、柔軟性と構成が可能です。たとえば、Flaskを使用すると、代替のjsonパーサーをインストールして、個別のテスト実行でカバーされるものを使用できます。

Flaskのtox.iniからテストと毒について多くを学ぶことができます

最も低いテストバリアントは、最も古い依存関係バージョンに対してテストするように注意します。

develは、コア依存関係の開発バージョンに対してテストしています。

フラスコはより高いレベルの複雑さであり、注意深いテストスイートを示しています。

ピラミッドのtox.iniは、同様の数の環境を示しています(100%のコードカバレッジも目指しています)。

mayaのtox.iniは非常に新鮮(2日)でシンプルです。ここでも4つの異なる環境があり、py27はpy35やpy36とは凍結要件が異なります。

@ Moritz90
pipenvとtoxの間の接着剤について

  • pipenv --manは、いくつかの手順、 tox.iniコマンド内でpipenvを使用する方法を示しています
  • tox-pipenvはいくつかの追加の統合を提供しようとしていますが、現時点では混乱しています。

tox.iniファイルでは任意のコマンドを実行できるため、これにはpipenv含まれます。

pipenvは優れた機能があり、すでにアクティブ化されているvirtualenv(toxベースのテストの場合)で実行すると、特定の仮想envにインストールされます。 これは本当にいいです。

おそらくPipfile.lock生成する必要があるため、それを取得して適切な場所に移動するには、追加の作業を行う必要があります(次のテストで上書きされないように、 .tox/py36/Pipfile.lockに移動します。これは可能ですが、ある程度単純化されます。 Pipfile場所の環境変数を使ったトリックを使えば、さらに簡単になるかもしれません。

@vlcinsky

  • setup.py-問題を理解できるかどうかはまだわかりません。 pipenv install -e . 1回実行すると、setup.pyがロックファイルを介して追跡されるようになります。 そして、setup.pyに新しいパッケージを追加するたびに、 pipenv install実行します。
  • ロックファイルの更新を忘れている開発者- pipenv --deployはこれをキャッチするように設計されています。 CIで実行してください!
  • Pipenvは失敗します-ツールにバグがある場合、それは
  • トックス

    • Toxがテストの管理に適している場合、それは素晴らしいことです。 パッケージや決定論的ビルドの管理にも最適な場合は、さらに優れています。

    • しかし、それが本当なら、Pipenvが存在する理由はありません。 ですから、Toxにはある種の制限があるとしか思えません。

    • 上記と同様に、今日の世界の状態(優れた相互運用性の欠如)は、哲学を拒否する理由のようには聞こえません。

  • 複数の環境

    • ここには、Flaskのような特別なケースが少なくともいくつかあることは明らかです。

    • 複数のロックファイルについてのより良い提案はありません(ただし、この点でPipenvの将来の機能があるのではないでしょうか?)

    • しかし、この場合でも、複数のロックファイルの管理が実際の問題であるとはまだ確信していません。 最悪の場合、ローカルで単純なスクリプトupdate-all-lockfiles.sh作成し、CIでpipenv --deployしてエラーをキャッチできるようです。


@ Moritz90-同意しました。ほとんどの場合、「2フェーズ」アプローチはやり過ぎかもしれません。 特に、ロックファイルに意図的/意図的な「手動」更新を行う場合は、完全に不要です。


より一般的には、この「提案」が実際に難しい問題に焦点を当てていることを確認するのがよいでしょう(私の見解では、それは(A)複数の環境にサービスを提供し、(B)アップストリームの依存関係の変更をキャッチしたい)。 一時的なもの(Pipenvのバグ)や、ツールの使用目的に関する潜在的な誤解に基づくべきではありません。

しかし、これらの「難しい」問題の場合でも、フレーミングは「一部の複雑なエッジケースでは、基本的なPipenvワークフローが不十分であることがわかる場合があるため、ここで考慮すべきことがいくつかあります」のようにする必要があります。 IMO、デフォルトのアプローチとして組み立てるべきではありません(ほとんどの人がそれらの懸念を持っていないため)。

Pipenv / Pipfileがlib-dependenciesapp-dependencies 、およびdev-dependencies処理を許可する場合、@ vlcinskyが提供するドキュメントの例はより単純で混乱が少なくなります。 ドキュメントは次のようになります。

パッケージが共有ライブラリである場合は、 lib-dependenciesオプションを使用します。 例Pipfile

[lib-dependencies]
some-lib=="*"
another-lib=="*"
yet-another-one==">=1.0"

[dev-dependencies]
some-dev-tool=="1.1"

共有ライブラリの場合、コンシューマシステムでのバージョンの競合を防ぐために、バージョン範囲をできるだけ広く[lib-dependencies]未満に保つことが重要です。

パッケージが、正確な依存関係バージョンを必要とするアプリケーション(pipenvによってターゲットシステムにインストールされることを意図している)である場合は、 [app-dependencies]オプションを使用する必要があります。 例Pipfile

[app-dependencies]
some-lib=="1.0.12"
another-lib=="1.*"
yet-another-one=="2.0"

[dev-dependencies]
some-dev-tool=="1.1"

/ドキュメントの例を終了

別のアプローチは、 Pipfile.libPipfile.appます。

このようなものでは、ギャップを埋めるためにアンチパターンセクションやサードパーティツールのチャンクが不要になると思います。

pipenvパッケージングツールを呼び出すことは、Pythonライブラリを作成すること、またはそれらの作成に深く関与することを期待している場合、誤解を招く恐れがあります。

これは本当の問題だと思います。それは多くの混乱につながります。 特に、他のプログラミング言語(JS、Rust、Elmなど)でマネージャーをパッケージ化することに慣れている人々の間で。 Pipenvとsetup.pyを間違った方法で使用していることに気付くまで、数か月かかり、GIthubの問題をときどき読んでいました。

@feluxe

あなたの[lib-dependencies]またはPipfile.libは、今日Pipfile (抽象的な依存関係として-可能な限り広い)。

[app-dependencies]またはPipfile.appは、(特定の依存関係として) Pipfile.lockです。

pipenvとそのファイルは、ライブラリの開発またはアプリケーションデプロイメントの準備という、2つの異なる状況で使用できますが、両方で同時に使用することはできません。 このため、 Pipenvセクションを追加する強い理由はわかりません。 Pipfileがどのような目的に役立つかを知るのは、開発者の責任です。

これは本当の問題だと思います。それは多くの混乱につながります。 特に、他のプログラミング言語(JS、Rust、Elmなど)でマネージャーをパッケージ化することに慣れている人々の間で。 Pipenvとsetup.pyを間違った方法で使用していることに気付くまで、数か月かかり、GIthubの問題をときどき読んでいました。

同意しました。 3セクションのソリューションも、私が考えたことのない非常に興味深いソリューションであり、正しく、(驚くべきことに!)単純なようです。

私自身Pythonのバックグラウンドから来て、Nodeのpackage.jsonが間違っているといつも感じていました(コンパイラとリンカーがあり、後の段階でこれを解決できるので、Rustの方が優れています)。 アプリとライブラリの依存関係を同じように扱うことは、少なくとも抽象的な意味では、Pythonのようなスクリプト言語では機能しません。つまり、それはあなたにとっては機能するかもしれませんが、Pipenvのような汎用ツールは必要があるためそれを行うことができません。ジェネリック。

私は概念的には3つのセクションのソリューションが好きですが、それでも既存のエコシステムに対してはかなり互換性のない変更です。 このスペースを埋めるsetup.py、setup.cfg、および(潜在的に)pyproject.tomlがすでにあります。 Pipenv(Pipfile、正確には)がスペースに移動させたい場合は、それが関連などピップなどのプロジェクト、(ライブラリのサポートは、理想的には、それによって直接サポートされなければならない)とを統合する必要がフリット

lib / appの依存関係の処理に関する他の問題で述べたように、この議論はpypa-dev(メーリングリスト)やPEPプロセスにエスカレーションする必要があります。そうすれば、Pipenvの前に、他の関係者や関係者がよりよく聞くことができます。 (Pipfile)はどの方向にも移動できます。

@vlcinsky

あなたの[lib-dependencies]またはPipfile.libは、今日Pipfileにあるものです(抽象的な依存関係として-可能な限り広い)。

これが明確でない場合は申し訳ありません。 私のlib-dependenciesは、人々が現在setup.py / install_requires入れたものを意味します。 たぶんpypi-dependenciesは私が意味したことのより良い名前でしょう。

@uranusjr

このスペースを埋めるsetup.py、setup.cfg、および(潜在的に)pyproject.tomlがすでにあります。

Pipenv(コマンドラインツール)はsetup.pyインターフェイスできます。 setup.pyの依存関係セクションだけをPipfileに移動する必要があります。 少なくとも私の想像では:)

lib / appの依存関係の処理に関する他の問題で述べたように、この議論はpypa-dev(メーリングリスト)やPEPプロセスにエスカレーションする必要があります。そうすれば、Pipenvの前に、他の関係者や関係者がよりよく聞くことができます。 (Pipfile)はどの方向にも移動できます。

わかりました、ご迷惑をおかけして申し訳ありません;)時間があれば、メーリングリストに何か書きます。

ただし、この提案の範囲内では、Pythonパッケージングコミュニティ全体の新しいワークフローを作成するといううさぎの穴に入るのではなく、現在可能なベストプラクティスに焦点を当てることをお勧めします。 現在の制約の中でのベストプラクティスを提案し、その後、改善のための議論を開始するために、より生産的になるだろう。

@ uranusjr-私は「コンパイルされた」バックグラウンドから来ているので、なぜこれが当てはまるのか興味がありますか?

アプリとライブラリの依存関係を同じように扱うことは、Pythonのようなスクリプト言語では機能しません。

@ tsiq-olivercアプリのベストプラクティスでは依存関係を固定する必要があるため、同じソースの要件ファイルを使用している場合、ライブラリも依存関係を固定し始めます。 これにより、依存関係の解決に問題が発生します。

私のアプリには2つの依存関係AとBがあり、どちらもCに依存していますが、Aはv1をピン留めし、Bはv2をピン留めしているとします。 コンパイルされた言語を使用すると、ツールチェーンはコンパイル時にこれを検出し、さまざまな方法で解決できます。 たとえば、Rustはリンク時にこれを実行します。最終実行可能ファイルには、Cの2つのコピー(v1とv2)が含まれ、AとBがそれぞれにリンクします。 C ++ランドでは、これはダイナミックライブラリで解決されます。 シンボルルックアップは後で(実行時に)実行されますが、考え方は同じです。コンパイラは(使用するインターフェイスから)必要なものを認識し、それに応じて動作できます。

スクリプト言語は、実際に呼び出しに到達するまで、実際に何をしたいのかわからないため、これを行うことはできません。 Nodeは、依存関係に互換性がないと常に想定することでこれを回避します(2つのコピーが同一であっても、AとBは常に独自のCを取得します)が、新しいクラスの問題が発生し、ピアの依存関係のような厄介なハッキングが発生します。 (私は願っていますか?)同意はひどいです。 Pythonはおそらくそこに行きたくないでしょう(とにかく、それは既存のすべてのPythonインストールを壊す可能性があるのでできません)。

これを回避する別の方法は、依存関係のバージョンを「固定解除」するパッケージツールで何か賢いことをすることです。 (Rubyの)Bundlerは、ロックファイルをgemに含めないように推奨することでこれを行います。これにより、Bundlerは、Gemfile.lockの固定バージョンではなく、Gemfileの固定されていないバージョンを使用できます。 しかし、人々はアドバイスを無視して好きなことをする傾向があるので、あなたはまだどこでもピン留めされたバージョンを手に入れます。

私はおそらくそれが単に機能しないと言うには少し強すぎました。 しかし、少なくとも以前のすべての試みは失敗しました、そして試みた人々の多くは非常に賢い人々であり、私よりはるかに賢いです。 私はこれが個人的にできるとは思いません、そして私は実際にそれをする非常に素晴らしい提案を見るまでこのように考え続けます。

@ tsiq-oliverc Pieter Hintjensは、「コメントはプルリクエストの形で歓迎されます」という概念をどこかに書いています。

それが哲学的なアドバイスから本当に具体的で実用的なものに焦点を移すので、私はそれが好きです。 また、コメント投稿者は、アイデアが不完全であるか、実際の使用で何らかの形で壊れていることを学習することが多いため、コメントの数も制限されます。

pipenvが適切に使用されている(または少なくとも使用されている)Pythonライブラリの例を尋ねましたが、何も提供していませんでした。

あなたはtox品質についてコメントしていますが、それに慣れていないことを認め、Pythonパッケージ開発の世界でのベストプラクティスについて何かを繰り返しています。

Flaskはおそらく特殊なケースだとあなたは言います。 そこで、Githubで「ライブラリ」という単語を使用してPythonプロジェクトを検索し、フォークの数で並べ替えて(おそらく、Linuxで開発を行っている人の数を反映しているため)、すべての「キュレートされた何かのリスト」を無視し、1つの環境の数を数えました。 OS(通常はLinux):

テストを実行する環境の実際の数は、ほとんどの場合2(+ Windows)または3(+ OSX)倍になります。

toxは、3つのうち2つのプロジェクトで使用されます(TravisやAppveyorは別のレベルのテストを行うため、比較しません)。

テストする環境の数はかなり多く、Flaskは間違いなく最もワイルドな環境ではありません。

固定依存関係を定義する環境の数は、実際には手動で管理することはできません。

Pipfile.lockをリポジトリにドロップするだけではかなり簡単ですが、魔法のような改善はありません(そうであれば、状況が改善される実際のシナリオを見せてください)。

たぶん、あなたは「コンパイルされた」世界からの黄金律を知っていて、決定論(または再現性)がPythonにとっても必須であると感じているかもしれません。 ご覧のとおり、実際に多くのPythonプロジェクトはそれなしでうまく機能しているので、ここでは黄金律がそれほど厳密に適用されていない可能性があります。

状況を改善するPythonライブラリのpipenv使用法を見つけたら、私は幸せです。 そして、全体的な品質を損なうような使用を防ぎたいと思います。

その目標を達成するために、私のアプローチは質問を繰り返すことです。

  • ツールを使用しますか?
  • どのように?
  • なぜ、私はどのような価値を得ましたか?
  • それはいくつかの問題を引き起こしましたか? (余分な作業、エラーが非表示になっています...)

@feluxe

これが明確でない場合は申し訳ありません。 私のlib依存関係は、人々が現在setup.py / install_requiresに入れているものを意味します。 たぶん、pypi-dependenciesは私が意味したことのより良い名前でしょう。

この号のpbr説明を参照してください。 これは、Pipfileによるライブラリの依存関係をサポートするための取り組みです。

1つのPipfileを2つの目的(libとapp)に使用するのではなく、これらを別々に行う必要があると思います。 本当に必要だと感じたら、それを使ったプロジェクトの目的を教えてください。 私は通常、ライブラリの開発プロジェクトと展開プロジェクトは時間の経過とともにまったく異なる使用法になるため、それらを分離しておくようにしています。

@vlcinskyどこでこれを取りたいのかよくわからないので(どのようなPRを求めているのかとりあえずこの会話

私の立場のTL; DRを言い換えると:

  1. 決定論的ビルドは非常に望ましく、ソフトウェア業界の他の場所では一般的であり、Pipenvで簡単に実現できます。
  2. 確かにいくつかのエッジケースがあり、誰かが(回避策またはより良いツールを介して)最先端を前進させる必要があります。
  3. (2)ケースの小さなサブセットに影響を与えるという理由だけで、Pipenvのドキュメントが(1)に対して全面的に推奨することは無責任です。

@uranusjr了解しました。 ここには言語固有のものはないと思いますが、一般的な解決策がない問題に対処するために、さまざまなコミュニティがさまざまなヒューリスティックに決着をつけているだけです。バージョンの競合がある場合は、問題が発生します。

たとえば、Maven / Javaは、ビルド時にそれについて考えるように強制します。 NPMの方法は、不一致のバージョンがインターフェイスを通過する場合にランタイムの問題が発生することを意味します。 ランタイム解決(Python、ダイナミックライブラリなど)は、扶養家族がクラッシュする可能性があることを意味します。 依存関係のバージョンが期待したものではない場合。

@vlcinsky

この号のpbrの説明を参照してください。 これは、Pipfileによるライブラリの依存関係をサポートするための取り組みです。

pbrは素晴らしく、すべてのように見えますが、これで対処しようとしていたカテゴリに分類されます。

このようなものでは、ギャップを埋めるためにアンチパターンセクションやサードパーティツールのチャンクが不要になると思います。

そもそもそのようなツールは必要ないはずだと思います。

本当に必要だと感じたら、それを使ったプロジェクトの目的を教えてください。 私は通常、ライブラリの開発プロジェクトと展開プロジェクトは時間の経過とともにまったく異なる使用法になるため、それらを分離しておくようにしています。

pypiパッケージに関しては、開発依存関係の処理にPipenvを使用し、開発依存関係を説明するためにPipfileを使用し、 install_requiressetuptools lib依存関係を説明するためにsetup.pyを使用することになりsetuptoolssetup.py実行している私のパッケージを公開するためにpipenv run python setup.py bdist_wheel upload 。 これは私が複雑だと思うものです。

他の現代語では、1つのコマンドラインツール(パッケージマネージャー)と1つの依存関係ファイル形式を学ぶ必要があります。 ドキュメントは1つの場所にあり、簡単にフォローできます。初心者は、これらすべてを数時間で整理できます。 それはnpm initnpm install foo --devnpm publishです。 Pipenv / Pipefileはすでにそのほとんどを実行できますが、すべてを実行できれば、このような問題は存在しません。

私は、この議論のために一種の「コミュニティ」セクション/ウィキを求める私の呼びかけを再解釈します。 いくつかの「パターン」は合法であり、私たちの中には「Pythonライブラリのやり方」を共有したい人もいれば、私のようにpbrを使っている人もいれば、非常に良いパターンを持っている人もいます。 しかし、pipenvドキュメント内のページは、それが良い考えかどうかはわかりません。

PS:新しいpypiへの移行を準備するには、python setup.pyuploadではなくtwineを使用する必要があります。 「アップロード」の使用は、アンチパターンと見なす必要があります。

たぶん、pipenvは「公開」コマンドを増やすことができますか?

@feluxeあなたは詩を見たいと思うかもしれません。 私はそれを偶然見つけました、そしてそれはあなたが探しているもののようです。

それはpipenvが行うことなどを実行し、特に依存関係の管理に関してはより適切に実行するようです(少なくともそれが彼らのふりをしていることです)。 依存関係の管理、パッケージ化、およびすべての単一ツールpoetry公開を行います。

pipenvpoetryは、最終的にPythonに真のパッケージマネージャーを提供するための努力を集めることができるのだろうか。

この議論が行き過ぎる前に、もう一度繰り返したいと思います。 Pipenvは、単にpublishコマンドを拡張したり、パッケージングの義務を引き継ごうとすることはできません。 誰もがこのように行うわけではないため、これはエコシステムをさらに断片化するだけであり、アプリとライブラリの依存関係は理論的に異なるため、ワークフローで区別が行われると、誰かにそれらをマージして戻すように指示することはできません。

ほとんどすべての人がこのマージに参加しているように見えるかもしれませんが、実際には、物事がうまくいき、他のことをしているため、このディスカッションに参加しない人がたくさんいます。 私は繰り返し言いました:ツールチェーンとファイル形式の設計を改善することについての議論はPythonパッケージ階層のどこかで行われるべきです、それでそれはPipenvが依存するより基本的なものを設計する人々により多くの露出を受け取ります。 そこで議論してください。 Pipenvはそれを変更する立場にないので、ここでそれを示唆する意味はありません。

私は繰り返し言いました:ツールチェーンとファイル形式の設計を改善することについての議論は、Pythonパッケージ階層のどこかで行われるべきです。そのため、Pipenvが依存するより基本的なものを設計する人々により多くの露出を受け取ります。

パッケージ化と公開が行われたため、このバグに関する議論が制御不能になることに同意します(このバグは依存関係の管理に関するものです!)が、この議論を行う適切な場所を教えてください。 人々は、pipenvが正しい方向への切望されたステップと見なされているため、pipenvのメンテナに追加の責任を課したいという理由ではなく、ここでそれを持っています。

編集:申し訳ありませんが、新しいコメントを初めて読んだときにあなたがまさにそれをした投稿を見逃したに違いありません。

ただし、この提案の範囲内では、Pythonパッケージングコミュニティ全体の新しいワークフローを作成するといううさぎの穴に入るのではなく、現在可能なベストプラクティスに焦点を当てることをお勧めします。 現在の制約の範囲内でベストプラクティスを提案してから、改善のための議論を開始する方が生産的です。

私はこれに非常に同意します。 私たちは、最初のライブラリのメンテナのための最高の可能なワークフローは、今、我々は大きな計画を思い付く前にあるかを把握する必要があります。 それでは、このスレッドの冒頭で行ったように、もう一度それに焦点を当てましょう。 まだ結論に達していないようです。

トピックに戻る:依存関係をライブラリの別のファイルで定義する必要がある理由についての@uranusjrの投稿を引用します。

これを回避する別の方法は、依存関係のバージョンを「固定解除」するパッケージツールで何か賢いことをすることです。 (Rubyの)Bundlerは、ロックファイルをgemに含めないように推奨することでこれを行います。これにより、Bundlerは、Gemfile.lockの固定バージョンではなく、Gemfileの固定されていないバージョンを使用できます。 しかし、人々はアドバイスを無視して好きなことをする傾向があるので、あなたはまだどこでもピン留めされたバージョンを手に入れます。

私はおそらくそれが単に機能しないと言うには少し強すぎました。 しかし、少なくとも以前のすべての試みは失敗しました

今のところ、ライブラリの公式推奨事項がCIビルドにpipenvを使用できない理由はわかりませんが、 Pipfile.lockはソース管理から外してください。 数人の人が指摘しているように、 pipenvは現在、パッケージングプロセスとは何の関係もないので、上記で概説した問題に遭遇することはありません。

また、これが、アプリケーションが抽象依存関係を定義するために使用するのと同じファイルで抽象依存関係を定義することに反対する議論である理由もわかりません。 pipenvPipfilesetup.pyと統合するための複雑なソリューションを実装したくない場合pipenv問題ありませんが、それが一般的に悪い考えである理由はわかりません。

@vlcinsky

1つのPipfileを2つの目的(libとapp)に使用するのではなく、これらのことを別々に行う必要があると思います。

上記の投稿を参照してください。 なぜそう思うのか詳しく教えてください。 原則としてマイナス面は見当たらない。 現時点では、 Pipfileを含めるのは悪い考えかもしれません。これは、2つの異なるファイルで同じ方法で依存関係を定義する必要があるためですが、その理由を説明する引数はまだ見ていません。一般に、依存関係の宣言にPipfileを使用するのは悪い考えです。

私と同じ状況でない限り、 Pipfile.lockをライブラリのソース管理に含めるべきではないことにすでに同意していることに注意してください。

編集:また、 pipenv自体が実際に違いを知る必要があることが判明した場合は、 app-dependencieslib-dependencies導入を開始する前に、貨物のcrate-typeフィールドのようなものを導入するだけかもしれません。 lib-dependencies -それは非常に複雑に聞こえます。

@ Moritz90 Pythonのメーリングリストのいくつかは、この議論を行うのに適した場所です。

pypa-devは、Pythonパッケージングとその周辺のエコシステムを中心とした議論にとって最も明確です。 同様の議論を投稿するのであれば、おそらくここから始めます。

python-ideasはアイデアについて話し合う場所であり、Pythonコミュニティ全体に対して非常に高い可視性を備えています。 これをPEPレベルにプッシュしたい場合にも、これは良い出発点になると思います(最終的にはそうなると思います)。

@ tsiq-oliverc

PRとは、つまり、コンセプトが実行可能であることを証明する例を示してください。

それで、いくつかの既存のライブラリを拾い上げて、それをフォークして、あなたの(1)を適用してください-あなたはそれがpipenvで簡単であると言って、私に見せてください。 私はかなり一生懸命に努力し、困難を抱えています。

あなたの(2)が「他の誰かが仕事をしなければならない」という意味の場合、あなたのPRは存在しません。

(3)では、実数を与えずに「ケースの小さなサブセット」について話します。 virtualenvの数に関して説明したすべての上位ライブラリは「小さなサブセット」と見なされますか?

この議論を締めくくるために、私は議論中に発見されたものの短い要約を作成しました。

焦点:Pythonライブラリとアプリケーションのpipenv (アンチ)パターン

焦点を少し変更しました。(一般的な)Pythonライブラリだけでなく、アプリケーションについても説明しています。これを含めるのはかなり安価であり、違いをよく示しています。

pipenvtoxなど、既存のツールの変更を提案するものはすべて意図的に除外しました。

pipenvとは何ですか?

  • これはデプロイメントツールであり、 Pipfile.lockを使用して具体的な依存関係を定義および適用できます。
  • これはvirtualenv管理ツールです。
  • Pythonパッケージを生成するという意味でのパッケージツールではありません。

ライブラリとアプリケーション

(Pythonソフトウェア)製品は、別の製品(つまりライブラリ)で使用する準備ができているか、実行する準備ができている最終的なアプリケーションです。

個人的には、「エンタープライズライブラリ」でさえライブラリカテゴリに分類されると思います(同じルールが適用され、実行コンテキストの数だけが少なくなります)。

ソフトウェア製品の種類

  • ライブラリ:別の製品(ライブラリまたはアプリケーション)で使用されます
  • アプリケーション:デプロイして実行する

インストール方法:

  • ライブラリ: pipenv install <package>したがって、「パッケージを使用できるようにします(他のライブラリのバージョンを解決します)」
  • アプリケーション: pipenv syncしたがって、「具体的な依存関係を適用する」

抽象的で具体的な依存関係

ソフトウェア製品の依存関係

  • 抽象依存関係:使用するライブラリに名前を付ける必要があり、バージョンや使用法を制限する可能性がありますが、十分な柔軟性を維持する必要があります(バージョンを固定しないでください)
  • 具体的な依存関係:バージョンを固定する必要があります。理想的には、使用済みライブラリのハッシュを使用します。

    pipenvアーティファクト:

  • Pipfile :抽象的な依存関係

  • Pipfile.lock :具体的な(ロックされた)依存関係 "

実行コンテキスト

異なる実行コンテキストの典型的な数

  • 図書館:

    • 1つのOS上のpythonvirtualenvs:3から9(30を使用する竜巻)

    • OS数:1〜3(Linux、OSX、Windows)

    • 総数:3〜18

  • 応用:

    • 1つのOS上のpythonvirtualenvs:1

    • OSの数:1

    • 総数:1(またはごくわずか)

CIの目標、優先順位、決定論

CIの目標

  • 図書館:

    • コードを含む。 抽象的依存関係により、実行コンテキストの予想されるすべてのバリアント内でのインストールと予想される機能が可能になります。

    • (プライベート/パブリック)pypiが依存関係ライブラリの更新を取得すると、テストされたライブラリの関数のインストールに影響する場合は失敗します。

  • 応用:

    • インストールされると(具体的/固定された依存関係を使用して)、期待されるすべての機能が1つの事前定義された実行コンテキスト内で提供されます

機能に関する特定のCIの目標:

  • 図書館:

    • ライブラリによって宣言された抽象的な依存関係は完全であり、必要なすべての制限が含まれています(必要な場合のみ):ライブラリはそれ自体を適切にインストールします

    • 予想されるすべてのユースケースは適切に機能します

  • 応用:

    • 具体的な依存関係は完全であり、すべてが固定されています。 ハッシュ:アプリケーションは正しくインストールされます

    • 予想されるすべてのユースケースは適切に機能します

さまざまなCIテストモード

  • モード:「実行、フォレスト、実行」

    • 今日のPythonライブラリの大部分はこの方法でテストされています。

    • toxまたは同様のテストソフトウェアを使用する

    • pipenv使用なしと具体的な依存関係(ライブラリには問題ない場合があります)

  • モード:「生成して封印する」

    • リポジトリにPipfileがありません

    • Pipfile.lockによって作成されたpipenv install -e .

    • Pipfile.lockは環境を文書化(シール)し、問題を分析するために後でvirtualenvを複製できるようにします。

  • モード:「氷河期」

    • 二相試験

      • 抽象依存関係( setup.py install_requires内で定義)の変更またはpypiの依存パッケージが更新されたら、 Pipfile.lockpipenv install -e .

    • 関数テストの実行:ライブラリコードが変更されたときに実行します。 pipenv sync Pipfile.lockによって作成されたvirtualenv内で実行されます

      誰がどのようにPipfile.lock作成できるか

  • 開発者が手動で(アプリケーションで機能する場合があります)

  • CIビルドによって自動的に(そしてすべてのテストに合格し、検証済みのアーティファクトであると宣言します)

決定論と柔軟性の優先順位

  • ライブラリ:柔軟性(可能な場合はいつでも実行)
  • アプリケーション:決定論(選択した実行コンテキスト内でまったく同じ方法で実行)

    インストールされた製品の決定論に影響を与える可能性のあるもの:

  • public pypi(決定論が低く、パッケージはいつでも更新されます)

  • プライベートpypi(より高い決定論、パッケージの更新が制御される可能性があります)
  • ライブラリ内の抽象的な要件(決定論には使用しないでください)
  • 具体的な要件( Pipfile.lock ):完全な決定論

その他

Pipfile.lockいくつかのユースケース:

  • (アンチパターン)ライブラリの抽象依存関係を定義します(抽象でなければならないため)
  • (アンチパターン)テストされたライブラリのvirtualenvを設定します(壊れたライブラリの抽象的な依存関係を隠す可能性があります)
  • テストが実行された正確なvirtualenv(「シール」)を文書化します(したがって、開発者は後で壊れたテストのためにそれを再作成し、そこで実験することができます)
  • テストされたアプリケーション用にvirtualenvを設定します
  • アプリケーションを本番環境にデプロイする

    その他のヒント

  • pbrライブラリでは、 requirements.txt介して抽象ライブラリの依存関係を定義できます。 Pipfile読んで更新が進行中です。

  • poetryパッケージはpyenv似たものを試します

    一般的な問題

  • 「ロックファイルをリポジトリにドロップ」すると、決定論的なビルドが得られます。

    • アプリケーションで動作します。
    • 実行コンテキストは非常に多く、それぞれが異なるPipfile.lock可能性が高いため、ライブラリでは機能しません。 真剣に: flaskは、11の異なる仮想環境(1つのOS上)に10の異なるロックされた依存関係を示しています。 誰がそれらを作成してコミットするのですか?
    • 「生成して封印する」CIモードでも、 Pipfile.lock (ただし、CIスクリプトによって生成される)を取得して、他の場所でvirtualenvを再生成できることに注意してください。
  • ライブラリリポジトリのPipfile.lock

    • virtualenvの作成に使用すると、 setup.py内のライブラリ依存関係の壊れた定義を隠すことができます。

  • ライブラリリポジトリのPipfile

    • 抽象依存関係( setup.py内で定義される)を繰り返す場合、壊れたsetup.py依存関係宣言を非表示にする可能性があります。

    • 推奨:依存関係もテストする必要があり、それらがsetup.py 「テスト」エクストラとして宣言されている場合は、 pipenv install -e .またはpipenv install -e .[tests] Pipfileを生成します。

  • CIスクリプトにpipenv install <something>を追加する

    • それ自体では決定論をあまり改善しません

    • 「生成して封印する」CIモードを参照してください(その後、virtualenvへのすべてのインストールはpipenv経由する必要があります)。

結論

Pythonライブラリ(特に一般的なライブラリ)は、予想外に多数の実行コンテキストを示します。 その理由は、ライブラリの目標は、さまざまな条件下での柔軟性が証明されているためです。 柔軟性は、決定論的なビルドよりも重要であるように思われます。 「コンパイル」の世界から来た人々にとって、これは非常に悪いアンチパターンのように感じるかもしれません。 実際のところ、ほとんどの(おそらくすべての)Pythonライブラリは決定論的なビルドを提供しておらず(いくつか知っている場合はお知らせください)、Pythonはまだ非常にうまく機能しています。 Pythonアプリケーションが生きている理由は次のとおりです。スクリプト言語としてのPythonは、コンパイルされた世界とは異なります。 他の理由は、決定論が(ライブラリのセットから構築された)アプリケーションが決定論の(自然で正当化された)要件を解決するとすぐに、ステップ後に解決できる(しなければならない)ということである可能性があります。

アプリケーションの場合、状況は正反対であり、ここでは、 pipenvなどのツールを使用して決定論に到達するのは非常に簡単です。

次はどうする?

  • 来週か2週間はこれに対処する時間がありません。
  • どこかに一連のブログエントリを作成することを想像できます(どこにあるかはわかりません)。 場所を知っている場合(理想的にはいくつかの議論を許可する)、コンテンツを参照し、議論し、最終的に(存続する場合は)石のどこかに置くのが自然な場所です:-)。
  • 私は@uranusjrにこの問題の制御を引き継ぐことを提案します(それを閉じ、次に何をするかを決定し、人々を他の場所にリダイレクトするか、実用的と思われるものは何でも)

非常に刺激的な議論をしてくれた皆さんに感謝します-「私はこのトピックで完全に失われました」というメッセージが3回リファクタリングされたように感じます-これは自然に私たちが良くなったという意味です。

@vlcinsky poetrypyenvとは何の関係もありません。 これはpipenvによく似ていますが(ただし、ライブラリとアプリケーションの管理、IMOに関してははるかに優れた実装です)、パッケージ化と公開の部分があります。

プロジェクトとその依存関係(抽象的な依存関係)を定義するpyproject.tomlファイルと、固定された依存関係を記述し、Pythonのバージョンとプラットフォームpyproject.toml固定されたpyproject.lockがあります。 pipenvが直面している問題を回避するために、確定的ロックファイルを1つだけ持つようにfileが指定しました。 インストール時にのみ、 poetryは、インストールするパッケージを環境と照合してチェックします。

また、ライブラリをパッケージ化するときに、(固定された依存関係ではなく)抽象依存関係を使用するため、パッケージを配布するときの柔軟性を維持できます(たとえば、PyPIを介して)。

これの利点は、ライブラリに抽象的な依存関係を使用し、アプリケーションにロックファイルを使用することです。 これは両方の長所です。

固定された依存関係を使用しない@zfaceの詩は、文字通り目的全体を打ち負かしています。 Pipenvは_idempotent_であり、これには環境の_再現_が必要です。 この問題をプラットフォームとして使用するのをやめて、作成者がCLIを気に入らないというpipenvで使用する最初の理由としてリストされているものをすべての人に販売してみてください。 結局のところ、当社のソフトウェアは数十万台のマシンに展開され、実際にパッケージングに関するベストプラクティスを認識して使用しています。 べき等な環境を望まず、開発とパッケージングの境界線を曖昧にしたい場合は、この方向に進んでおらず、生産性が低いため、このディスカッションには参加しないでください。

基本的に、私たちは回復力に多くの時間と労力を費やします。高尚な主張をする小さなプロジェクトは、人々がエッジケースにぶつかっていないため、それほど多くの労力を費やす必要はありません。 別のツールがすべての世界で最高のものを提供すると本当に信じている場合は、それを使用することをお勧めします。pipenv自体は、短期的にはパッケージングを処理しません。

@techalchemy私は何も販売していません。実際、私はpipenvで使用できるアイデアに向けているだけです。

また、 poetryは、 pipenvPipfile.lockと同じように、 pyproject.lockで依存関係を固定します。 つまり、 pipenv提供するのと同じように複製できます。 ロックファイルがある場合は、それが使用され、固定された依存関係がインストールされます。私が間違っていない場合は、 pipenv同様です。

抽象依存関係を使用するのは、プロジェクトを配布用に(つまり基本的にライブラリ用に)パッケージ化するときだけです。この場合、依存関係を固定する必要がないためです。

@vlcinskyまだ整理、修正、または拡張する必要のあるポイントがいくつかありますが、私はまだこれをドキュメントフォーム、Pipenvなどに入れることに非常に熱心です。 プルリクエストの送信に興味がありますか? 記事の具体化をお手伝いさせていただきます。

詩に関しては、私は個人的には全体としてファンではありませんが、それは多くの正しいことをします。 Pipenv開発者が人々を押し付けたいいくつかのベストプラクティスに違反しているため、Pipenvドキュメントではおそらく言及されるべきではありませんが、パッケージングの全体像を提供するために、議論がpypa-devなどで行われる場合は言及されるべきです。エコシステムは現在です。

詩はまた、より多くの注意と貢献を使うことができます。 これは、Pipenvを含むコミュニティにとって最適です。 実行可能な選択肢があれば、人々は最初にPipenvの頭に入って、期待したことをしていないと不平を言う代わりに、自分の選択に重きを置くことができます。 ライブラリ間の良好な競争は、依存関係の解決の面で技術的な改善を促進する可能性もあります。これは、Pipenvと詩の両方が行います(完全ではありません)。 私たちはお互いから多くを学ぶことができます。

@uranusjrはい、明確にされており、より多くの聴衆と共有するに値するものはほとんどないと思います。 あなたの援助は本当に大歓迎です。

「ペアドキュメンテーションドラフティング」はどうですか? 現時点では、2人程度の小規模な作業が最も効果的だと思います。

やろうと思っているのは(おそらく1回か2回の反復で):

  • 正確にそれを公開できる場所
  • ドキュメントアイテム(記事、セクション)を特定する
  • 各項目の範囲と目標を明確にする
  • 概要に同意する
  • 未解決の問題を特定する
  • それらを解決する
  • ドキュメントを書く
  • 公開する(そしてそれが受け入れられることを願っています)

(議論されたことに基づいて)自分でそれを書きたいと思っていて、私をレビュアーとして持っていれば、私は文句を言いません。

次の行動に同意するために、電子メールでご連絡します。

@vlcinskyまた、リアルタイムのやり取りが必要な場合は、 PySlackers (Slackワークスペース)で@uranusjrとして利用できます。 Pipenvにはそこにチャネルがあります( #pipenv )。

@uranusjrそれは私が努力を集めることによって意味したことです。 Pythonには、貨物のような優れたパッケージマネージャーがどうしても必要です。 Pythonエコシステムは、物事を行うための標準的な方法がないため、他の言語と比較して見劣りします。 そして、 pipenvはそれを助けないと思います。

私を悩ませているのは、 pipenv自分自身をthe officially recommended Python packaging toolとして宣伝しているのに、それはパッケージングツールではなく、ユーザーにとって誤解を招くことです。 これは、virtualenvマネージャーと組み合わせた単なる依存関係マネージャーです。

また、パイプはそうではないが、依存関係マネージャーと一緒にパッケージングツールである貨物、npm、糸に触発されたとあなたは言います。

そして、ここにpipenvの欠陥があります。人々は、 requirements.txtsetup.py以前と同じ間違いを犯すので、水を濁らせるだけです。 そのため、プロジェクトは依然として不適切にパッケージ化されており、 setup.py不適切に定義された依存関係があります。 それが、貨物のようなプロジェクトが正しく行ったことです。プロジェクト/アプリケーションの開発のすべての側面を処理して一貫性を確保しますが、 pipenvようなプロジェクトはそうではありません。

そしてあなたが言うとき:

Pipenvと詩の両方が行うこと(そしてどちらも完全ではない)

どう言う意味ですか? 私が見たところ、彼らの依存関係マネージャーは、 pipenvによって提供されるものよりもはるかに回復力があります。 唯一の欠点は、PyPI JSON APIを使用していることです。これは、パッケージの公開が不適切なために依存関係情報がない場合があります。

とにかく、あなたが言ったように、私は両方のプロジェクトがお互いから学ぶことができると思います。

そして、もう1つ、最終的にpipがPipfile処理する場合、pipenvの将来はどうなるでしょうか。 それは単にvirtualenvマネージャーになるのでしょうか?

詩の依存関係マネージャーがjsonapiに依存している場合、「不適切に公開されたパッケージ」が原因で間違っていることがあるだけでなく、実際に正しく解決できるものが非常に制限されます。 ウェアハウスのjsonapiは、古いバージョンを扱っている場合でも、_最新の_依存関係を投稿します。それは、その情報が含まれている場合です。 以前はjsonapiも組み込んでいました。高速だったので素晴らしかったのですが、インフラストラクチャチームから信頼しないように言われました。 信頼性の低いソースに最初から依存している場合、回復力のあるものと呼ぶのは少し不誠実なようです。

結局のところ、課題は、セットアップファイルを実行する依存関係グラフを実際に作成することです。これは、現在、パッケージングがどのように機能するかを示しているためです。 それを回避する方法はありません。 私のマシンで解決される依存関係グラフは、同じパッケージであっても、マシンで解決される依存関係グラフとは異なる場合があります。

手を振るのは簡単で、「pipがpipfileを読み取ることができれば、pipenvをvirtualenvマネージャーにするだけではありませんか?」と言うのは簡単です。 いいえ。Pipenvは依存関係マネージャーです。 べき等環境を管理し、再現可能なロックファイルを生成します。 あなたはそれを振り払ってこのツールをvirtualenvマネージャーに還元しているので、これはあなたにとって些細なことのように思えるかもしれませんが、そうではありません。 ロックファイルを解決し、持っていない、使用していないPythonバージョンのマーカーを含め、それを利用できるようにして、プラットフォームやPythonバージョン間で正確にデプロイおよび複製できるようにします。 ローカルホイールとファイル、vcsリポジトリ(グラフもそこで解決)、リモートアーティファクト、pypiパッケージ、プライベートインデックスなどの処理を含むいくつかの解決方法を使用します。

結局のところ、pipはpipfileを処理します。これが計画であり、フォーマットが作成されてからの計画です。 しかし、それは「しかし、pipが要件ファイルを処理できるのはいつですか?」と尋ねるのと同じです。 質問は基本的に同じです。 Pipはそのフォーマットをインストールできます。 (ちなみに、pipを使用して)ファイルもインストールすることを除いて、私が説明した機能のいずれにも実際には関係ありません。

@techalchemy

ウェアハウスのjsonapiは、古いバージョンを扱っている場合でも最新の依存関係を投稿します。それは、その情報が含まれている場合です。

これはまったく間違っています。 https://pypi.org/pypi/{project}/{release}/json呼び出すことで、特定のバージョンの依存関係を取得できます。 https://pypi.org/pypi/{project}/json呼び出すだけで、最後の依存関係のみを取得できますが、実際には正しい依存関係のセットを取得できます。

そして、Pythonプロジェクトのパッケージ化/公開部分は、JSON APIを確実に使用できるようになるため、最終的にはすべての人に利益をもたらすため、本当に改善する必要があります。

べき等環境を管理し、再現可能なロックファイルを生成します。
ロックファイルを解決し、持っていない、使用していないPythonバージョンのマーカーを含め、それを利用できるようにして、プラットフォームやPythonバージョン間で正確にデプロイおよび複製できるようにします。

そして、 poetryです。 また、JSON APIを使用しないようにして、 pipenvと同じ解決方法を使用するようにすることができます(pip-toolsを使用)。 https://github.com/sdispater/poetry/issues/37#issuecomment -379071989を参照してくださいpipenv (https://github.com/sdispater/poetry#dependency-resolution)よりも復元力があります。 )

@zfaceこれを最後に持っていってください。 Pipenvは、公式に推奨されているPythonパッケージツールであることを自称していません。 だからと言っています。 それが不適切だと思われる場合は、 Pipenvを推奨する担当者に伝えてください。 これらのものをPipenvdevに置かないでください。 これは苦情を申し立てるのに間違った場所であり、ここで苦情の解決策を得ることができない可能性があります。 また、そこにある技術的な質問に対してより良い回答を得ることができます。 これはPipenvの問題追跡システムであり、PythonパッケージツールとPythonパッケージの実行方法に関するディスカッション掲示板ではありません。

Pipenvは、解決のためにpip-toolsに依存しているだけではありません。理解が不足していることを示す、ソフトウェアを1つのライナーに減らすのはやめてください。 PyPI APIがどのように機能するかをよく知っているので、それを実装したチームと直接話をしました。

これはまったく間違っています、

このような態度はここでは歓迎されません。 私たちが話していることを理解していないと思い込まないでください。 礼儀を練習してください。

それでもpipenvよりも回復力があります(https://github.com/sdispater/poetry#dependency-resolution)

Pipenvは現在、依存関係グラフをフラット化しません。 木が平らになり、ツール全体がより良く、より弾力性があると主張する1つの特定の問題を指摘するのは愚かです。あなたは、単にピペンを侮辱し、詩を宣伝するためにここにいることを何度も証明しています。 途中でお願いします。この動作は歓迎されません。

私は、議論がトピックから大きく外れていることに同意します。それは、pipenvの周りの「グッドプラクティス」を活用しようとしていました。

しかし、

[...]は、requirements.txtとsetup.pyで以前と同じ間違いを犯します。 そのため、プロジェクトは引き続き不適切にパッケージ化され、setup.pyで不適切に定義された依存関係があります。

私はこの意見を共有します。新しい開発者が自分のPythonコードを正常にパッケージ化するには、実際には複雑で、複雑すぎて、多くのオンラインドキュメントへの道を読む必要があります。
しかし、それを完全に処理するのは、pipenvやその他のパッケージの依存関係次第ではありません。 歴史を書き換えることはできませんでした。 私たちはコミュニティとして、Pythonツールチェーンを段階的に最新化する方法を見つける必要があります。

そして、pipenv(そしておそらく詩)は非常に良い前進です。

一方の側でアプリケーション用にPipfileを維持し、もう一方の側でライブラリ用にsetup.pyを維持する必要があるのは簡単です。 たくさんの言葉や長い記事、グッドプラクティスガイドでどれほど難しい説明をしても、それが何であるかには複雑すぎます。 今のところこのようなものであることに完全に同意しますが、それは私たちがより良い、より安全な方法を想像することを妨げるべきではありません。
最後に、開発者として、私を助け、私の人生をできるだけ楽にするために、おそらく2つの異なるモードを備えた単一のツールが必要です。

彼らが行う部分だけを抽出する方法でなければなりませんrequirements.txt/Pipfile 「簡単にsetup.py」のようなものを提案するなどPBRなどLIBSからの、Pipfile対応のラッパーはarroundのinstall_requiresせずに、 pbrがもたらすすべての不要な動作を、それだけを行う専用のsetuptoolsラッパーにパッケージ化します。

だから私たちはそれぞれの世界をより良くすることができるでしょう:

  • Pipfileを維持するためのpipenv(ライブラリとアプリケーションの両方でバージョン管理されています)
  • Pipfile.lockを維持するためのpipenv(アプリケーション専用にバージョン管理されています)
  • この魔法のラッパーパッケージ( pipfile_setuptoolsinstall_requires_pipfile ?)を使用します。これは、 Pipfileinstall_requiresに注入するだけの第1レベルの依存関係になります。

この別のプロジェクトはpipenvとは関係ありませんが、一般的なPipfileパーサーライブラリが必要です。 どう思いますか?

私の理解PyPAから@gsemetが率いる、代わりにpyproject.tomlでそれを埋めるためにしようとしてきたフリット。 ソース形式としてPipfileを使用する前に、まず(pypa-devまたはdistutils-sigで)彼らと話し合う必要があります。 Pipfile(およびロックファイル)の解析に関しては、 pypa / pipfile (Pipenvベンダーがコア解析ロジックを提供するため)で処理されます。


編集:どちらかのメーリングリストでこれについての議論を始めることにした場合は、私にメッセージを送ってください。 Pythonパッケージ配布の2つの部分をどのように組み合わせることができるかについていくつかのアイデアがあります。

pyproject.toml (PBRによって行われるsetup.cfgとしての役割を引き受けます)で宣言された依存関係を見るのは少し悲しいことを認めなければなりませんが、PyPaはPipfileもサポートしています...。

flitとpipfileへのポインタをありがとう。 軽く見えるケネスライツ

PBRのsetup.cfgは、公式ドキュメント(例: data_files )と比較してより完全であるように見え、複数のツール(flake8、pytestなど)で既に共有されているファイルを再利用すると、同じファイルを使用できるため、 Pythonプロジェクトのルートにあるファイル)

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