はじめに
私がPipenv
というものを知って、使い始めてから半年くらいが経ったので、
便利だな〜って思ったところをまとめていきます。
簡単に言うとPipenv
便利だからみんなも使ってみてねって記事です。
これまで
Pipenv
の存在を知るまではvenv
を使って仮想環境を作り、requirements.txt
に記載されたモジュールをpip
でインストールする形で管理していました。
requests==2.22.0
こんなファイルを準備して
$ python3 -m venv venv
$ ./venv/bin/python -m pip install -r requirements.txt
Collecting requests==2.22.0 (from -r requirements.txt (line 1))
Using cached https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl
Collecting idna<2.9,>=2.5 (from requests==2.22.0->-r requirements.txt (line 1))
Using cached https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests==2.22.0->-r requirements.txt (line 1))
Using cached https://files.pythonhosted.org/packages/b9/63/df50cac98ea0d5b006c55a399c3bf1db9da7b5a24de7890bc9cfd5dd9e99/certifi-2019.11.28-py2.py3-none-any.whl
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests==2.22.0->-r requirements.txt (line 1))
Using cached https://files.pythonhosted.org/packages/b4/40/a9837291310ee1ccc242ceb6ebfd9eb21539649f193a7c8c86ba15b98539/urllib3-1.25.7-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests==2.22.0->-r requirements.txt (line 1))
Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl
Installing collected packages: idna, certifi, urllib3, chardet, requests
Successfully installed certifi-2019.11.28 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.7
こんな感じですね。
この環境でコード実行する場合はsource ./venv/bin/activate
するか、./venv/bin/python
を直接指定するかです。
これまでの問題点
これまでのモジュールの管理のしかただといくつか問題がありました。
依存しているモジュールがわかりづらい
requests==2.22.0
最初、このrequirements.txt
の書き方だと、依存しているモジュールのバージョンが固定出来ない事が気になりました。
しかし、pip
コマンドにはfreeze
というサブコマンドがあり、現在インストールされているすべてのモジュールをrequirements.txt
に記述出来る形式で出力してくれます。
その結果私のrequirements.txt
はこうなりました。
certifi==2019.11.28
chardet==3.0.4
idna==2.8
pkg-resources==0.0.0
requests==2.22.0
urllib3==1.25.7
これで依存モジュールまですべてバージョンが指定出来ます!ただここで大きな問題が、
モジュールの依存関係が全くわからない
後述しますが、この点でわたしはPipenv
が手放せない体になりました。
現状のrequirements.txt
ではインストールされるすべてのモジュールを列挙しただけなので、それぞれの依存関係がまったくわかりません。
またプロジェクトによってはdev-requirements.txt
やbuild-requirements.txt
にファイルが別れていたりして(私の開発してるプロジェクトがそうだった)、
モジュールのバージョンひとつあげようとしても一苦労。どれが依存しているパッケージだか分からないので、一旦別環境にインストールしてみて依存パッケージを確認したりしていました。
コード実行までが面倒くさい
仮想環境を作ってコードを実行するまで、私は以下のような手順を実行していました。
$ python3 -m venv venv # 仮想環境作成
$ ./venv/bin/pip install -U setuptools pip wheel # 基本モジュールを最新版にする
$ ./venv/bin/pip install -r requirements.txt # 必要なモジュールのインストール
$ ./venv/bin/python main.py # 仮想環境でコードの実行
なーがいっ!一度作成したvenv環境をとっておけばいいんだろうけどそうもいかないものなのです。
Makefileを使えば気にならない
私はMakefile
を利用してこれをコマンドひとつで出来るようにしています。
venv:
python3 -m venv venv
./venv/bin/pip install -U setuptools pip wheel
./venv/bin/pip install -r requirements.txt
.PHONY: run
run:
${MAKE} venv
./venv/bin/python main.py
これでmake run
でいつでもコードが実行出来るようになります。
Pipenvを知ってしまった
ある日Pipenv
に出会った。。。
Pipenv
は公式のドキュメントがすごく良く出来てます。日本語だし読みやすい。
個人的にはこれがすごく助かりました。
Pipenvのよいところ
Pipenv
の機能自体は公式ドキュメントをみてもらえばわかると思います。
ここでは、Pipenv
を使ってみて今までの管理方法より、
便利になったと感じた機能をいくつか紹介していきます。
モジュールの依存関係がわかりやすい
これを言いたくてこの記事を書いたと言っても過言ではありません。
ここでは深く言及しませんが、Pipenv
ではrequirements.txt
の代わりにPipfile
というファイルでモジュールを管理します。
このファイルはpipenv
コマンド実行時に自動で生成されるので、直接編集する機会は少ないかもしれません。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
requests = "==2.22.0"
[requires]
python_version = "3.6"
ここでpipenv graph
というコマンドを実行してみます。
$ pipenv graph
requests==2.22.0
- certifi [required: >=2017.4.17, installed: 2019.11.28]
- chardet [required: >=3.0.2,<3.1.0, installed: 3.0.4]
- idna [required: >=2.5,<2.9, installed: 2.8]
- urllib3 [required: >=1.21.1,<1.26,!=1.25.1,!=1.25.0, installed: 1.25.7]
インストールされているモジュールが確認出来るのはもちろん、それぞれの依存関係まで一目瞭然。
これが個人的に一番ありがたかったです。
モジュールごとに求められているバージョンまでわかるので、バージョンを変えたいときなどにいちいち依存関係を確認する必要がなくなります。
コード実行までが簡単
Pipenv
を利用していると仮想環境の作成→必要なモジュールのインストール→仮想環境でコード実行まで以下のコマンドで出来ます。
$ pipenv install # 仮想環境の作成+必要なモジュールのインストール
$ pipenv run python main.py # 仮想環境でmain.pyを実行
コード実行までが面倒くさい で紹介した手順と比べると明らかにコマンドの数が減っています。
このくらいの量であればわざわざMakefile
を使う必要もなくなります。
scriptsを定義出来る
Pipfile
内にscripts
というセクションを定義することで、よく実行する文をコマンドとして定義出来ます。
詳細はこちら (公式)
例えばテストを実行するコマンドを定義したPipfile
が以下のようになります。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pytest = "==5.3.1"
[packages]
requests = "==2.22.0"
[requires]
python_version = "3.6"
[scripts]
test = "python -m pytest tests/"
[scripts]
というセクションが追記されています。
これはpipenv run
コマンドに続くサブコマンドを定義でき、この場合pipenv run test
でpytest
を使ったテストが実行されるようになっています。
testの実行や、パッケージングなど、よく使うコマンドはMakefile
に記述していたのですが、これを使えば簡単なコードを実行する程度であればPipfile
ひとつで済みます。
.envファイルを読み込んでくれる
pipenv run
でコードを実行する時、.env
ファイルを自動で読み込んでくれます。
詳細はこちら (公式)
これも地味にありがたい。
自分はこの機能は、設定ファイルのような使い方をしています。
.env
ファイルにkey=value
の形式で値を記述し、コード内では環境変数から値を読み取るようにします。
KEY=VALUE
import os
key = os.environ.get("KEY")
print(key) # VALUE
これだけで設定ファイルのように、.env
内のファイルを編集するだけで実行結果が変わります。
$ pipenv run python main.py
VALUE
コードの規模が大きくなればちゃんと設定ファイルを読み込む仕組みを作ったほうがいいですが、
小規模なコードではいちいちConfigParser
などを利用して設定ファイルを読み込むコードを書くのは手間なので、この機能はすごく助かってます。
Pipenv使ってみてね
Python
を使っている人でPipenv
初めて聞いたよって方々、ぜひ使ってみてください。