4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

OSSTechAdvent Calendar 2019

Day 4

Pipenvを使ってみた

Last updated at Posted at 2019-12-03

はじめに

私がPipenvというものを知って、使い始めてから半年くらいが経ったので、
便利だな〜って思ったところをまとめていきます。

簡単に言うとPipenv便利だからみんなも使ってみてねって記事です。

これまで

Pipenvの存在を知るまではvenvを使って仮想環境を作り、requirements.txtに記載されたモジュールをpipでインストールする形で管理していました。

requirements.txt
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を直接指定するかです。

これまでの問題点

これまでのモジュールの管理のしかただといくつか問題がありました。

依存しているモジュールがわかりづらい

requirements.txt
requests==2.22.0

最初、このrequirements.txtの書き方だと、依存しているモジュールのバージョンが固定出来ない事が気になりました。
しかし、pipコマンドにはfreezeというサブコマンドがあり、現在インストールされているすべてのモジュールをrequirements.txtに記述出来る形式で出力してくれます。

その結果私の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.txtbuild-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を利用してこれをコマンドひとつで出来るようにしています。

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コマンド実行時に自動で生成されるので、直接編集する機会は少ないかもしれません。

Pipfile
[[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が以下のようになります。

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 testpytestを使ったテストが実行されるようになっています。
testの実行や、パッケージングなど、よく使うコマンドはMakefileに記述していたのですが、これを使えば簡単なコードを実行する程度であればPipfileひとつで済みます。

.envファイルを読み込んでくれる

pipenv runでコードを実行する時、.envファイルを自動で読み込んでくれます。
詳細はこちら (公式)

これも地味にありがたい。

自分はこの機能は、設定ファイルのような使い方をしています。
.envファイルにkey=valueの形式で値を記述し、コード内では環境変数から値を読み取るようにします。

.env
KEY=VALUE
main.py
import os
key = os.environ.get("KEY")
print(key)  # VALUE

これだけで設定ファイルのように、.env内のファイルを編集するだけで実行結果が変わります。

$ pipenv run python main.py
VALUE

コードの規模が大きくなればちゃんと設定ファイルを読み込む仕組みを作ったほうがいいですが、
小規模なコードではいちいちConfigParserなどを利用して設定ファイルを読み込むコードを書くのは手間なので、この機能はすごく助かってます。

Pipenv使ってみてね

Pythonを使っている人でPipenv初めて聞いたよって方々、ぜひ使ってみてください。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?