web-dev-qa-db-ja.com

Python依存関係の地獄:virtualenvとグローバル依存関係の間の妥協?

Pythonこれまでのところ、プロジェクトの依存関係を管理するためのさまざまな方法をテストしました

  1. すべてをグローバルにpipでインストールする(スペースを節約しますが、遅かれ早かれ、問題が発生します)
  2. pip&venvまたはvirtualenv(管理が少し面倒ですが、多くの場合は問題ありません)
  3. pipenvとpipfile(venv/virtualenvよりも少し簡単ですが、遅く、一部のベンダーロックの仮想環境は、実際のプロジェクトフォルダー以外の場所に隠れています)
  4. パッケージおよび環境マネージャーとしてのconda(パッケージがすべてcondaで使用可能である限り、pipとcondaの混合は少しハッキーです)
  5. 詩-私はこれを試していません
  6. ...

これらすべて(1を除く)の問題は、ハードドライブの容量が非常に速くいっぱいになることです。私は開発者ではないので、Pythonを毎日の作業に使用しています。したがって、何百もの残念ながら、80%のプロジェクトでは、「大きな」パッケージが必要です:numpypandasscipymatplotlib -あなたが名前を付けます。典型的な小さなプロジェクトは約1000〜2000行のコードですが、venv/virtualenv/pipenvに800MBのパッケージ依存関係があります。事実上約100 GB以上ありますpython仮想依存関係で満たされた私のHDDの.

さらに、これらすべてを各仮想環境にインストールするには時間がかかります。私はWindowsで作業していますが、多くのパッケージはWindowsのpipから簡単にインストールできません:ShapelyFionaGDAL-プリコンパイルされたホイールが必要です Christoph Gohlke 。これは簡単ですが、ほとんどのワークフローに影響します(たとえば、pipfileの_pip install -r requirements.txt_または_pipenv install_)。 40%がパッケージの依存関係をインストール/更新していて、コードの作成に費やしている時間は60%に過ぎないと感じています。さらに、これらのパッケージマネージャーはいずれも、コードの公開とテストに実際に役立つことはないため、他のツール(例: setuptoolstox、_semantic-release_、twine...

私は同僚と話しましたが、彼ら全員が同じ問題に直面しており、誰も実際の解決策を持っているようには見えません。私はいくつかのパッケージを持つためのアプローチがあるかどうか疑問に思っていました。グローバルにインストールされているほとんどのプロジェクトで使用するもの-たとえば、numpypandasscipymatplotlibは、pip with _C:\Python36\Lib\site-packages_または_C:\ProgramData\Miniconda3\Lib\site-packages_のcondaを使用-これらは、問題を頻繁に壊さない、よく開発されたパッケージです。とにかく、私はとにかく私のプロジェクトですぐにそれを修正したいと思います。

他のことはローカルのvirtualenv-foldersに入るでしょう-現在のワークフローをpipenvからcondaに移動したくなります。

そのようなアプローチはまったく意味がありますか?少なくとも最近、Pythonには多くの開発があり、おそらく私がまだ見ていなかった何かが浮かび上がりました。このような混合されたグローバルローカル環境でファイルをセットアップする方法に関するベストプラクティスのガイダンスはありますか。 Gitlab、Githubなどを通じて開発プロジェクトを共有するために_setup.py_、_requirements.txt_または_pyproject.toml_を維持する方法落とし穴/警告は何ですか?

この素晴らしいブログ投稿 もあり、Chris Warrickがそれをかなり完全に説明しています。

[更新]

半年後、Condaを使用することで私の問題のほとんどが解決したと言えます。

  • すべてのシステム、WSL、Windows、ネイティブLinuxなどで実行されます。_conda env create -f myenv.yml_はすべてのプラットフォームで同じです
  • ほとんどのパッケージはconda-forgeですでに利用可能です。独自のパッケージをconda-forgeで受け入れるのは簡単です
  • condaにないパッケージについては、conda環境にpipをインストールし、pypiからpipを使用してパッケージを追加できます。ヒント:_conda update --all -n myenv -c conda-forge_は、pipでインストールされたパッケージではなく、condaからのパッケージのみを更新します。ピップインストールされた依存関係は、_pip install pack_name --upgrade_を使用して手動で更新する必要があります。 condaでpipを使用してパッケージをインストールすることは、通常は avoided である緊急ソリューションであることに注意してください
  • Strictまたはopen _environment.yml_を作成して、condaチャネルの優先度、condaからのパッケージ、pipからのパッケージを指定できます
  • これらのymlsから単一のステートメントでconda環境を作成できます。 _Miniconda3 Docker_を使用して、Gitlab Continuous Integrationで開発環境をセットアップする-これにより、テストの実行が非常に単純かつ簡単になります。
  • ymlsのパッケージバージョンは、状況に応じて、厳密またはオープンに定義できます。例えば。 envをPython 3.6に修正できますが、このバージョン範囲のセキュリティ更新(例:3.6.9)を取得させることができます)
  • 私はcondaがWindowsのcコンパイルされた依存関係のほとんどすべての問題を解決することを発見しました。 Windowsのconda envは、何らかの理由でパッケージマネージャーを使用できないWindowsエンドユーザーに配布できる実行可能コード(テスト済み!)にフリーズするpythonコードを許可します。
  • 「大きな依存関係」の問題に関して:多くの特定の(つまり小さな)およびいくつかの非特定の(つまり大きな)コンダ環境を作成することになりました。たとえば、かなり大きな_jupyter_env_があり、jupyter labとほとんどの私の科学パッケージがインストールされています(numpy、geos、pandas scipyなど)-これらのツールにアクセスする必要があるときはいつでもアクティブにして、それらを1か所で最新に保つことができます。開発用特定のパッケージの場合、パッケージの依存関係にのみ使用される追加の環境があります(例:_packe1_env_)。全体で約10の環境があり、管理可能です。いくつかの汎用ツールがベースコンダ環境にインストールされています。 pylint。警告:pylint/pycodestyle/autopep8などをVS Codeで(たとえば)機能させるには、python-code-dependenciesを含む同じ環境にインストールする必要があります-それ以外の場合は、未解決のインポート警告
  • Windows用のminicondaを Chocolatey パッケージマネージャーでインストールしました。私はそれを_conda update -n base conda_で最新に保ち、_conda update --all -n myenv -c conda-forge_で私の環境は週に1回は魅力のように機能します!
  • 新しい更新:最も素晴らしい機能の1つ:新しい_--stack_フラグにより​​、conda環境をスタックできます。 _conda activate my_big_env_次に_conda activate --stack dev_tools_env_( 2019-02-07 現在)を使用すると、多くの環境でいくつかの汎用パッケージを使用できるようになります
  • 新しいアップデート2:_Windows Subsystem for Linux_(WSL)のcondaを使い始めました。これによりワークフローが大幅に改善されました。パッケージはWSLに直接接続されたWindowsのVS Code Insidersで作業でき、Linux環境のpythonパッケージでのバグははるかに少なくなります。
  • はい、conda envの特定のパッケージ間の互換性の問題に遭遇しましたが、ごくまれです。 2つのアプローチがあります。安定して動作する必要がある重要な環境である場合は、_conda config --env --set channel_priority strict_を有効にします。これにより、互換性のあるバージョンのみがインストールされます。パッケージの組み合わせが非常に少なく、まれであるため、これにより、解決できない依存関係の競合が発生する可能性があります(つまり、envを作成できません)。この場合、私は通常、実験的開発用に小さい環境を作成し、パッケージを減らして_channel_priority_をflexible(デフォルト)に設定します。より低いpython strictでは解決できないこれらの実験的環境のバージョン、たとえば_conda create -n jupyter_exp_env python=3.6 -c conda-forge_を試すことも良いアプローチです。最後の手段のハックは、 condaのパッケージリゾルバーを回避するpip(ただし、不安定な環境やその他の問題が発生する可能性があるため、警告が表示されます!)まず、環境にpipを明示的にインストールしてください。

全体的な欠点の1つは、大きなconda-forgeチャネルを使用すると、condaが少し遅くなることです。それらは それに取り組んでいます ですが、同時にconda-forgeインデックスは非常に急速に成長しています。

16
Alex

問題

あなたは、どのアプローチも完全に解決できないかもしれない多くの問題をリストしました:

  • スペース

'「大きな」パッケージが必要です:numpy、pandas、scipy、matplotlib ...事実上、私はpython仮想依存関係で満たされた私のHDDの約100+ GBを持っています'

  • 時間

...これらすべてを各仮想環境にインストールすると時間がかかる

  • 出版

...これらのパッケージマネージャーはどれも、コードの公開とテストに実際には役立ちません...

  • ワークフロー

現在のワークフローをpipenvからcondaに移動したくなります。

ありがたいことに、あなたが説明したのは、循環依存、依存関係の固定、バージョン管理など、パッケージマネージャーを悩ます典型的な依存関係の問題ではありません。


詳細

私はWindowsでcondaを長年にわたって同様の制限の下で使用しており、妥当な成功を収めています。 Condaは元々、scipy関連のパッケージのインストールを簡単にするために設計されました。まだあります。

「scipyスタック」(scipy、numpy、pandasなど)を使用している場合、condaが最も信頼できる選択肢です。

コンダcan

  • scipyパッケージをインストールする
  • c拡張機能と非Pythonパッケージをインストールします(numpyおよびその他のパッケージを実行するために必要)
  • パッケージにアクセスするには、condaパッケージ、condaチャネル(これを調べる必要があります)およびpipを統合します
  • 仮想環境による依存関係の分離

コンダはできません

  • コードの公開を支援する

再現可能な環境

次の手順は、必要に応じてvirtualenvを再現するのに役立ちます。

  • Scipyパッケージをpipでインストールしないでください。私はコンダに頼って重い作業を行いました。それははるかに速く、より安定しています。あまり一般的でないパッケージをconda環境内にpipインストールできます。
  • 場合によっては、pipパッケージが環境内のcondaパッケージと競合する可能性があります(この問題に対処する リリースノート を参照)。

ピップ問題を回避:

私はいくつかのパッケージを持つためのアプローチがあるかどうか疑問に思っていました。ほとんどのプロジェクトで使用するもので、グローバルにインストールされます...その他のものはローカルのvirtualenv-foldersに配置されます

A.作業環境をベース環境から分離します。 workenv。これを、日常的な作業の大部分を実行するためのgoto、「グローバル」環境と考えてください。

> conda create -n workenv python=3.7 numpy pandas matplotblib scipy
> activate workenv
(workenv)>

B.動作環境の clone 内での一般的ではないpipパッケージ(または重みのあるcondaパッケージ)のインストールのテスト

> conda create --name testenv --clone workenv
> activate testenv
(testenv)> pip install pint

または、requirements.txtファイルを使用して、最小限のパッケージで新しい環境を作成します

C. virtualenvごとに、依存関係のバックアップをrequirements.txtと呼ばれるenvironment.yamlのようなファイルに作成します。オプションで、このコマンドを環境ごとに実行するスクリプトを作成します。 docs を参照してください。このファイルから将来の環境を作成します。

> conda create --name testenv --file environment.yml
> activate testenv
(testenv)> conda list

出版

パッケージングの問題は、_ PEP 518 を介してpyproject.tomlファイルが登場したことで勢いを増している進行中の別の問題であり、B作者による関連する ブログ投稿 を参照してください。 )。 flit または poetry などのパッケージツールは、この最新の規則を採用して、ディストリビューションを作成し、サーバーまたはパッケージインデックス(PyPI )。 pyproject.tomlの概念は、setuptoolsへの特定の依存関係がある従来のsetup.pyファイルから離れようとしています。

依存関係

pipenv および poetry のようなツールには、「ロック」ファイルを介して依存関係の問題に対処するための独自の最新のアプローチがあります。このファイルを使用すると、Pythonパッケージングの世界でこれまでにない、ディペンデンシーグラフの状態を追跡して再現できます(詳細はを参照してください)。Pipfileとsetup.py here )さらに、私はこれらのクレームの範囲をテストしていませんが、condaと組み合わせてこれらのツールを引き続き使用できるというクレームがあります。ロックファイルは標準化されていませんまだ、しかしコア開発者B.によるとキヤノン インタビュー将来のPythonパッケージング、(〜 33m)「そこに着きたい」

まとめ

Scipyスタックのパッケージを使用している場合は、conda(Recommended)を使用します。

  • スペース、時間、ワークフローの問題を保存するには、condaまたはminicondaを使用します。
  • アプリケーションのデプロイを解決するか、依存関係で「ロック」ファイルを使用するには、condaと組み合わせて次のことを検討してください。
    • pipenv:デプロイおよび作成に使用Pipfile.lock
    • poetry:デプロイおよび作成に使用poetry.lock
  • PyPIでライブラリを公開するには、次のことを考慮してください。
    • pipenvpipenv install -e.で開発し、手動で公開 twine
    • flit:自動的にパッケージ化して*公開
    • poetry:自動的にパッケージ化し、publish

関連項目

  • B. Cannonとのポッドキャストインタビューで、一般的なパッケージングの問題について説明しています pyproject.tomllock files および tools
  • パッケージング toolspipenv vs. pip、37m)と開発環境について議論するK. Reitzとのポッドキャストインタビュー。
4
pylang

私はいくつかのパッケージを使用するアプローチがあるかどうか疑問に思っていました。グローバルにインストールされているほとんどのプロジェクトで使用するもの...その他のものはローカルのvirtualenvフォルダに移動します

はい、virtualenvはこれをサポートしています。グローバルに必要なパッケージをグローバルにインストールし、virtualenvを作成するときはいつでも --system-site-packages オプションを指定して、作成されたvirtualenvが引き続きグローバルにインストールされたパッケージを使用できるようにします。 toxを使用する場合、適切なsitepackages=trueセクションに [testenv] を含めることにより、作成されたvirtualenvでこのオプションを設定できます。

10
jwodder

私の進捗状況の更新:

Condaパッケージマネージャーは、以下の理由により、pipenvよりもうまく機能することがわかりました。

  • デフォルトでは、グローバル依存関係はconda仮想環境内から利用可能です
  • 依存関係のインストール/更新時はpipenvよりも高速です
  • pipとcondaを組み合わせるのはそれほど問題ではありません。condaパッケージが利用可能な場合は、condaでインストールします。そうでない場合は、単にpipでインストールします。
  • environment.ymlを使用すると、環境と依存関係をLinuxとWindowsの両方で数秒で再作成できます。environment.ymlを使用すると、pipとcondaの依存関係を個別に指定できます(たとえば、これにより、Fiona、Shapely、 WindowsのGDalなど、condaバージョンを使用)
  • condaは、プラットフォーム間でパッケージ/依存関係を維持することの困難のほとんどを解決します(例:linux、mac、win)
  • conda(例:miniconda)を独立してpython install and use through conda runにインストールして使用することは問題ありませんでした。
  • environment.ymlがない場合、requirements.txtから環境変数を作成することが可能です(conda create -n new environment --file requirements.txt

残念ながら、environment.ymlを作成するプロセスは、どこにも一貫して記述されていないようです。しばらくすると、自動的に作成されたファイル(conda env export environment.yml手動で編集する必要があります 依存関係の最小限のリストが含まれていることを確認しました(インストールの残りはcondaに解決させます)。そうしないと、environment.ymlはシステム間で互換性がなくなります。

とにかく、このワークフローは上記で説明した私の問題のほとんどを解決し、pipenvやvirtualenvを使用する必要がなくなったことをうれしく思います。

まだいくつかの欠点があります、

  1. 複数のファイルで依存関係を維持する必要があります:

    • setup.py
    • environment.yml
  2. 環境内でプログラムを(ショートカットなどで)直接実行することはできません。これはpipenv runでは問題なく動作しますが、
    • conda runは自動的には実行されませんsource activate env
    • これは 未解決の問題 であり、いつか解決される可能性があります
  3. cx_freezeは外部のconda envからのグローバル依存関係を正しく含みません
  4. コンパイルが必要な依存関係(C-Extensionsなど)が必要な場合、condaは難しくなります。以下を参照するか、 here を参照してください
1
Alex