最近、Pythonでコードを書く機会が増えてきました。

  • インデント強制
  • 標準ライブラリで出来ることが多い
  • Python3からは仮想環境であるvenvが標準で利用できる

などの理由で主に使っています。
ただ、Webアプリケーションなどでライブラリが必要な場面に遭遇すると、easy_installpipなどのツールを利用してパッケージを取得することがあります。
今回はこのパッケージマネージャについてです。

他言語のパッケージマネージャとの比較

メジャーな言語には、たいてい強力なパッケージ管理ツールがあります。
以下は有名ですね。

  • composer(PHP)
  • RubyGems(Ruby)
  • cpan(Perl)
  • npm、yarn(JavaScript)
  • Maven(Java)
  • NuGet(C#)

依存関係の解決だけでなく、設定ファイルを書くことで開発・本番での場合分けや マルチプラットフォームでの環境の再現も容易に行うことができるものもあります。

ただ、先述したeasy_installpipでは、ここまで高度なことができません。
そこで、以下に続きます。

requirements.txt という選択肢

私は最近までこのやり方を使っていました。
Python3でvenvを使うやり方だと以下のような手順です。

# 仮想環境を作成
python -m venv venv

# 仮想環境に入る
# MacOS/Linux
./venv/bin/activate
# Windows
./venv/Scripts/activate

# pipでパッケージインストール
pip install 

# 現在インストールされているパッケージ群を書きだし
pip freeze > requirements.txt

ファイル名は何でも良いですが、一般的にこの名前が利用されているようです。
書き出したファイルには以下のように、ライブラリ名インストールされたバージョンというフォーマットで記録されます。

# requirements.txt
requests==2.18.4 
urllib3==1.22
...

インストール時は、読み込むrequirements.txtを指定してコマンドを実行します。

# pipでパッケージインストール
pip install -r < requirements.txt

問題点

ざっと思いつくだけでも以下があります。

  • 環境ごとにrequirements.txtを分ける必要がある
  • ライブラリに変更があるたびにファイル再生成する手間がかかる
  • そもそもバージョンアップの手順が面倒(仮想環境でインストール→ファイル再作成)

Pipenv という選択肢

そこで登場するのがPipenvです。
パッケージ自体は1年前ぐらいからあったようです。
未検証ですが、ドキュメントを読む限りPython2でも利用できるようです(可能な限りPython3を使ってとのことですが)。

Pipenv: 人間のためのPython開発ワークフロー

詳細は上記をご覧いただくとして、ざっと使い方を。

# pipenvをグローバルインストール
pip install pipenv

# プロジェクトフォルダで実行
cd 
pipenv install

requirements.txtがすでに存在するプロジェクトの場合、デフォルトで解析してくれます。
(ファイル名が異なる場合でも、-rオプションを使うことで読み込み可能です) コマンド実行後、プロジェクトフォルダに以下2ファイルが生成されます。

  • Pipfile (toml形式)
  • Pipfile.lock (JSON形式)

他言語のパッケージマネージャを使ったことがある方は名前からだいたい想像がつくと思います。
Pipfileが設定ファイル、Pipfile.lockがインストールされたライブラリの情報です。
また、このタイミングで仮想環境も自動で作成してくれます。

Pipfileは以下のようなフォーマットです。

[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"


[packages]

selenium = "==3.7.0"
requests = "==2.18.4"
python-dotenv = "==2.6.1"
...

[dev-packages]

ただ、requirements.txtからのインポートだと、上記のようにバージョンが完全に固定されてしまっています。
なので、必要に応じてバージョンを変更します。

パッケージを追加でインストールする際には以下のようにします。

pipenv install 

# dev-packages に追加する場合
pipenv install -d 

仮想環境で対象プログラムを実行するようなケースでも、Pipfileがあるディレクトリでpipenv runを利用することで実行可能です。

# pipenv run [実行したいコマンド]
pipenv run python main.py

都度「あれ?仮想環境入ってたっけ…?」「今入っている仮想環境はどのプロジェクトや?」とならないのでとても便利です。
ちなみに、デフォルトだと仮想環境はホームディレクトリの.virtualenvsディレクトリ内に生成されるようです。
これをプロジェクト直下(=Pipfileと同じディレクトリ)にしたい場合、以下のように環境変数を定義してインストールしてください。

PIPENV_VENV_IN_PROJECT=1 pipenv install

まとめ

複数人での開発だと、こういった機能は本当にありがたいですね。
待ち望んでいた機能なので、今後何らかの形で貢献できれば良いなと思っています。

※2020/9/19追記 こちらにて続編を書きました。