はじめに
答えは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.lockpip 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は簡単かつ正しい方法の提案になるかもしれず、どこかで確認したいな〜と思います ↩



