Pythonの開発環境構築にPipenvをつかっていると、ライブラリのバージョン管理のためにPipfile/Pipfile.lock(以下、両者の総称として"Pipfile"と呼びます)が使われます。
一方、Pipfile以前から使われてきたバージョン管理のファイル形式として、requirements.txtがあります。
なぜPipenvでは、既存のrequirements.txtでの管理を捨て、Pipfileを用いたバージョン管理を行うのでしょうか。
requirements.txtでのバージョン管理の問題点についてPipenvの開発者が触れている記事があったので、この内容を元に、Pipfileのメリットについて確認しようと思います。
https://www.kennethreitz.org/essays/a-better-pip-workflow
tl;dr
Pipfileを用いたバージョン管理は、以下を実現しています。
①全ライブラリのバージョンの固定
②バージョンアップ時の利便性
requirements.txtを用いたバージョン管理の問題点
requirements.txtの書き方のパターンとしては、主に以下の2つがあります。
- 最上位のライブラリのみ記載するシンプルな書き方。
- プロジェクトが依存する全てのライブラリのバージョンを指定する書き方。
①シンプルな書き方
requests[security]
flask
gunicorn==19.4.5
シンプルに必要なライブラリ名のみ記載する書き方です。
最低限の環境構築はこれを$ pip install
すれば十分です。バージョン指定のないライブラリは常に最新のバージョンをインストールする書き方です。
問題点
$ pip install
の結果インストールされるバージョンが毎回同じであることは全く担保されません。
公開するプロジェクトでは、基本的にはこの書き方ではNGです。
②全ライブラリのバージョンを指定する書き方
cffi==1.5.2
cryptography==1.2.2
enum34==1.1.2
Flask==0.10.1
gunicorn==19.4.5
idna==2.0
ipaddress==1.0.16
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
ndg-httpsclient==0.4.0
pyasn1==0.1.9
pycparser==2.14
pyOpenSSL==0.15.1
requests==2.9.1
six==1.10.0
Werkzeug==0.11.4
依存する全てのライブラリのバージョンを記載した、確実な方法です。
$ pip freeze
で生成されるのはこれですね。
誰がいつどこで$ pip install
しても、全く同じライブラリがインストールされます。
問題点
このリストを元に、依存関係を解決しつつ全てのライブラリのアップデートをするのは困難です。
一つの方法として、目視で最上位ライブラリを探し出し
$ pip install requests[security] flask --upgrade
でアップデートすることもできますが、非効率で、非確実です。
requirements.txtでのベストプラクティス
そこで元記事で提案しているのが、①シンプルな書き方と②全ライブラリのバージョンを指定する書き方を併用する運用フローです。
このフローでは、以下の二つのファイルを作成します。
- requirements-to-freeze.txt(①)
- requirements.txt(②)
requirements-to-freeze.txtにはプロジェクトで使用する最上位のライブラリのみを指定し、
$ pip install -r requirements-to-freeze.txt
したあと
$ pip freeze > requirements.txt
でrequirements.txtを生成します。
ライブラリのアップデートは
$ pip install -r requirements-to-freeze.txt --update
コマンドで行い、都度requirements.txtを更新します。
このフローでは、
- ①の問題点であったバージョンが固定されない点
- ②の問題点であったアップデートの煩わしさ
の両方が解決されています。
requirements.txtじゃだめ?
結論から言うと、上記の運用をすれば「だめ」ではなさそうです。
ですが、上記のフローで運用するならば、Pipfileが便利です。
ちなみに、名前からなんとなく想像できますが、①を担うのがPipfile, ②がPipfile.lockです。
Pipfileの詳細はこちらでご確認ください(丸投げ)