はじめに
答えはYesですか? nikkieです。
ふときっかけがあり、Python使いは皆pip freeze > requirements.txt
するのか文献調査しました。
わかったことを現在のバックアップとしてまとめます。
目次
- はじめに
- 目次
- きっかけ
- 暫定的な結論
- pip freeze > requirements.txt
- requirements.txtは手で作る!
- requirements.inという方法もある(pip-toolsを使う)
- 終わりに
- P.S. yamoryへのリクエスト
きっかけ
脆弱性管理クラウドyamoryを知りました🦎
Pythonプロジェクトにも対応したツールです!
yamoryはPythonプロジェクトをスキャンするとき、requirements.txt
という名前のファイルでプロジェクトの依存関係を出力しているのを前提とします。
pip プロジェクトのスキャンを行う際に requirements.txt が必要となります。
上記ドキュメントでは、pipを使っている場合はpip freeze
が案内されます。
またPoetryやPipenvの場合は依存ライブラリを出力してからrequirements.txt
を作るコマンドが案内されています(ありがたいですね)。
さて、小さい点なのですが、私はどうしても気になってしまいました。
どんなPythonプロジェクトでもpip freeze
の出力をrequirements.txt
という名前で保存するんでしょうか? 私、気になります!
念のためのおことわり
pip freeze
を使って環境を再現する考え方は私も採用しています。
pip freeze
を使わない方法をこの記事で取り上げるわけではありません。
pip freeze
を用いた環境の再現ですが、出力ファイルの名前には自由度があると考えます1。
カンファレンスや書籍でrequirements.txt
以外の名前にしている例も見聞きしていました。
こういった文脈を持つ私にとって、(重箱の隅だと思うのですが)requirements.txt
を前提にしたyamoryの案内はやや引っかかるものでした2。
なお、この記事は、上記の点が引っかかるという理由でyamoryを批評する記事でもないです。
暫定的な結論
文献調査まとめ
- 多数派と思われるやり方:
pip freeze > requirements.txt
requirements.txt
を開発者が書くやり方もある- その場合、環境の再現に使うファイルは
pip freeze > requirements.lock
で出力 requirements.txt
にはプロジェクトで直接依存するライブラリを書く
- その場合、環境の再現に使うファイルは
pip-tools
を使い、requirements.txt
を生成するやり方もある- 開発者は直接依存するライブラリを
requirements.in
に書く
- 開発者は直接依存するライブラリを
IMO:オススメ
- Pythonの開発にあまり慣れていないならば(この記事でいろいろ紹介しているが)
pip freeze > requirements.txt
がオススメ(守破離の守のフェーズ) pip freeze > requirements.txt
でやっていく中で、「直接依存するライブラリだけを管理したい」という経験を何回かしたら別のやり方に移行してみては(守破離の破のフェーズ)- 私は、個人の開発では
requirements.lock
やpip-tools
を(経験値を稼ぐ意味でも)使いたい
以降は文献調査の結果です。お楽しみください!
pip freeze > requirements.txt
これはよく見る方法だと思います。
pip
のUser Guideの「Requirements Files」を参照します:
python -m pip freeze > requirements.txt python -m pip install -r requirements.txt
今回確認したPython書籍では
- 『Python実践レシピ』3(1.1.3 requirements.txtを作って,複数の環境でバージョンを統一する)
- 『Effective Python 第2版』(項目83 隔離された複製可能な依存関係のために仮想環境を使う)
でも紹介されていました。
requirements.txt
は手で作る!
今回確認した範囲では、以下のやり方がありました。
- 手で作った
requirements.txt
をもとにpip freeze
pip freeze
を勧めない立場(少数派)
pip freeze > requirements.lock
methaneさん(稲田さん。Pythonのコミッター)の記事を参照します:
(1) requirements.txtを記載
Flask
(2) 開発環境でpip install -r requirements.txt
(3) 開発環境と同じ環境を再現する(本番環境やCI環境)
pip freeze > requirements.lock
pip install -r requirements.lock
で再現できる
requirements.lock
は、定期的に新しい仮想環境でpip install -r requirements.txt
をして更新します。
今回確認したPython書籍では以下で紹介されています。
- 『Python実践入門』(11.2の中の「環境の保存と再現」)
- 著者のrhoboroさんの登壇「自信を持ってコードを書こう」4でも紹介
- requirements.lockがコラムで一瞬登場する『エキスパートPythonプログラミング 改訂3版』
- 仕事でPythonコンテナをデプロイする人向けのDockerfile (1): オールマイティ編を参照しています(翻訳者の1人渋川さんが執筆)
「稲田さん、渋川さん、rhoboroさんと、Pythonに詳しい方はrequirements.lock
を使うのかな」という感想を持ちました。
形から入る(=できる人の真似をする)スタイルの私は自分で開発するときは、pip freeze > requirements.txt
よりもこちらの作法を推しています
pip freeze
は使わない
『エキスパートPythonプログラミング 改訂3版』の筆者の立場は独特でした。
pip freezeコマンドを使うと、現在の環境のすべてのパッケージを表示できますが、暗黙的に使うべきではありません。(Kindle の位置No.1199-1200)
全て読み通せてはいないのですが、pip freeze
の出力を使って環境の再現は行わないという主張みたい(?)です(完全に同じ環境を再現しなくてもいいということなのかな?)。
requirements.in
という方法もある(pip-tools
を使う)
いつか素振りしなきゃと積んでいた情報をこのたび評価しました。
pip-toolsを使います。
requirements.in
を手で作り、それをpip-compile
してrequirements.txt
を生成するようです。
上記のブログの概要を箇条書きで紹介します。
- Pythonプロジェクトの依存(dependency)には、directとtransitive5がある
- 例:Flaskを使うPythonプロジェクト
- Flaskがdirect dependency
- Flaskが依存するClickやJinja2などがtransitive dependency
pip freeze > requirements.txt
する- direct dependencyもtransitive dependencyも1つのファイルに記載される
- さて、Dependabotを使って、依存ライブラリを最新化したいとする
- Dependabotはrequirements.txtを見て、direct dependencyにもtransitive dependencyにもプルリクエストを作る
- transitive dependencyのバージョンを上げた際にインストールでエラーが発生(その時点でdirect dependencyが未対応)
- Dependabotはdirect dependencyだけを見てほしい
- そこで、
pip-tools
!- 開発者は
requirements.in
にdirect dependencyだけを書く pip-compile
で、transitive dependencyも加えたrequirements.txt
を生成requirements.in
をバージョン管理し、requirements.txt
はバージョン管理しない- Dependabotは
requirements.in
を見るので解決した(と理解した)
- 開発者は
実際のファイルの内容などは、ぜひ上記ブログをご確認ください。
終わりに
Pythonプロジェクトの環境の再現方法の細かい点「pip freeze
の出力を保存するファイル名」について、どんなやり方があるか見てきました。
思うに、Pythonのライブラリの管理方法って、簡単かつ正しい方法6がないんじゃないですかね(そういう意味で混乱と言えるかもしれません)7。
簡単な方法はpip freeze > requirements.txt
だと思います。
ただそれだと「direct dependencyだけを管理したい」というニーズはまかなえず、正しい方法としては伸びしろがあるんじゃないでしょうか。
正しい方法としてここで紹介したいくつかの方法が提案されているのだと思いますが、これらはpip freeze > requirements.txt
ほど簡単ではないので、それが普及のネックとなっているのかもしれません。
もしかするとnikkie的にはPoetryやPipenvを試すタイミングなのかもしれないですね。
ツールがファイルも管理してくれるので、「環境を再現する役割のファイルをどんな名前にするか」の追究自体が不要になりそうです。
P.S. yamoryへのリクエスト
requirements.txt
に開発者がdirect dependencyだけを書くケースがあるので、スキャン時にrequirements.txt
以外のファイルを指定できるとめちゃめちゃありがたいです!
脆弱性をスキャンする目的ではdirect dependencyだけを書いたrequirements.txt
では不足しており、transitive dependencyも含めたrequirements.lock
が目的に適うと考えています。
(requirements.txt
をバージョン管理している前提であれば、yamoryでスキャンするときだけpip freeze > requirements.txt
でrequirements.lock
と同じ内容にして対処できるかもしれません)
pip-tools方式は、direct dependencyだけを管理したい、かつ、yamory用にrequirements.txt
も生成したいを満たせそうですね。
- PoetryやPipenvのように出力ファイルがツール側で管理されていたら、この記事を書くきっかけの疑問は生まれなかったでしょう↩
- この点は引っかかりましたが、ツールとしてはかなり有用そうという印象です↩
-
『Python実践レシピ』は1.1.4でpipの
-c
オプションを紹介していました。-c
オプションは「世の中の殆どの Python 製アプリの開発では使う必要がないでしょう」という稲田さんのQiita記事(このエントリでも紹介)に納得した私は、取り上げたかった理由が何かあるんだと思いますが、試験の教科書として多くの人が読む本ではむしろ取り上げない方がよかったのでは、と思いました↩ -
アーカイブもあります ↩Python Charity Talks in Japan の13:10 ~ 13:40 の「自信を持ってコードを書こう」のスライドはこちらですhttps://t.co/fXpOqSETU1
— ほぼろ (@rhoboro) 2020年7月4日
#pycharity - ウィズダム英和辞典を引くと「他動(詞)の」とありました。Oxford Learner's Dictionariesに「used with a direct object」とあり、directと一緒に使われるがしっくり来ました(該当する訳語は浮かばないのですが)↩
- このブログでたびたび登場する「正しい使い方を簡単に、誤った使い方を困難に」の話題です↩
- (宿題)今回の調査で知ったPEP 621は簡単かつ正しい方法の提案になるかもしれず、どこかで確認したいな〜と思います ↩