pipenvの使い方メモ

久しぶりに更新するんだけど、アクセス履歴を見るとtotal PVが1200超えていて、未だに毎日何らかのアクセスがあるのがちょっと嬉しい。
今回は機械学習系じゃないが、今ちょうどBERTの亜種のSentence Bertを扱っているのでそのうち描こうかなーと思います。

書いてる理由

pythonでの開発にはこれまでpyenvを主に使っていたが、pipenvが便利そうなので今更ながらpipenvの利用メモを残す。

参考

Pipenvを使ったPython開発まとめ

概要

  • やりたいことの概要
  • pipenvのインストール方法
  • pipenvで指定したpythonのバージョンの環境を作成
  • pipenvで作成した環境にモジュールをインストールする
  • pipenvの環境をアクティベートする
  • pipenvの環境で実行するコマンドを定義する
  • pipenvで既存の環境を再現する

詳細

やりたいことの概要

ローカルで開発し、githubにpushして、それをサーバーでcloneしてローカルで開発したものをデプロイする。

f:id:raishi12:20201025214304p:plain
やりたいこと

pipenvの良いところは、pythonそのものやpythonで利用するモジュールのバージョン管理ができることと、それを別の環境に再現できるところ。
今回は、上記の手順を記載する。

pipenvのインストール方法(ローカル開発)

pip install pipenv

macなら brew install pipenvで入る。

pipenvで指定したpythonのバージョンの環境を作成(ローカル開発)

mkdir work_dir
cd work_dir
pipenv --python 3.7

これでwork_dir配下にて、python3.7の環境を作成するための準備が整う。
pipenv --python3.7のコマンドを実行すると、実行したディレクトリ配下にPipfileというファイルが作られる。
このPipfileには、開発に利用したpythonのバージョン自体や開発時に利用したモジュールなどが追記されていく形で環境の定義がされる。

Pipfile

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[requires]
python_version = "3.7"

pipenvで作成した環境にモジュールをインストールする(ローカル開発)

pipenv install torch==1.5

これで作成したい環境にpytorchの1.5をインストールすることが指定できる。
(現在のインタプリタにpytorchがインストールされるわけではない。)

上記コマンドを実行すると、Pipfileに自動でpytorchのインストール情報が追記される。

Pipfile

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
[packages]
torch = "==1.5"

[requires]
python_version = "3.7"

[packages]にバージョン付きでモジュール名が記述されている。
[dev-packages]は、pipenv install --dev torch==1.5のように--devをつけると、こちらに記述されるっぽい。
開発用にしか使わないパッケージはこっちで管理するのが良さそう?メリットが実感できていないけども。。

pipenvの環境をアクティベートする(ローカル開発)

pipenv shell

利用したいPipfileがあるディレクトリ配下で上記コマンドでアクティベートされる。
これでモジュールのimportなどが可能かどうかを確認できる。
また、作成したコードをこの環境で動作させる時はアクティベートされた状態でスクリプトを走らせる。
自分は開発はpycharmでやっているので、pycharmでpipenvを指定して開発した。 pleiades.io

これで、指定したpythonのバージョン/pythonで利用するモジュールを指定して開発を進める。
Pipfileの他にPipfile.lockというモジュールの依存関係を記述したファイルも一緒に出来上がる。

pipenvの環境で実行するコマンドを定義する(ローカル開発)

Pipfileに以下のように[scripts]を記述すると、pipenv run app_startなどで指定した処理の実行が可能になる。
他の人にこれを共有する場合などは、こっちの方がシンプルなので指定しておくのが良いかも。
ただし、pythonスクリプトの中で別ファイルをimportする時、Pipfileからの相対パスを指定しないとエラーになってしまったので書き換えた。ここが不便で、何か方法がないか調べたけどよく分からずだった。。。
Pipfileと同じ階層に.envファイルを作成して、そこでPYTHONPATHを指定して実行すると良い。

.env

PYTHONPATH=${PYTHONPATH}:work

実行時

source .env && pipenv run app_start

Pipfile

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
flask = "*"
transformers = "2.3.0"
numpy = "1.19.1"
scipy = "1.5.2"
torch = "1.4.0"
scikit-learn = "0.23.2"
pandas = "1.0.1"
fugashi = "1.0.5"
ipadic = "1.0.0"

[requires]
python_version = "3.7"

[scripts]
app_start = "python run.py"

ここまでで、利用するpythonのバージョン/インポートするモジュールの指定/実行コマンドの指定ができる。
開発したコードとPipfileとPipfile.lockを含めてgithubにpushし、別の環境にデプロイをかけていく。

pipenvで開発した環境を再現する(リモート)

以下の手順でローカルで作成した環境を再現して実行できる。

git clone hogehoge
cd hogehoge
pipenv sync
pipenv run app_start

pipenv syncはPipfile.lockで定義されたモジュールの依存関係を再現するために実行するっぽい。

pipenvで環境を作る際、以下のようなエラーで実行ができない時がある。

Warning: Your Pipfile requires python_version 3.7, but you are using 3.6.9 (/root/.local/share/v/b/bin/python).
  $ pipenv --rm and rebuilding the virtual environment may resolve the issue.
  $ pipenv check will surely fail.
Launching subshell in virtual environment...

pipenvでの環境構築は、その環境で利用できるインタプリタを使って構築がされるようで、上記の例だとpython3.7で環境を作りたいけどpython3.6.9しかないわってエラーになっているっぽい。
そのため、pyenvなどで利用したいバージョンのpythonをインストールしておき、pipenv --rmから再度pipenv syncpipenv run app_startなどとすると、無事実行できた。

以上!
pipenvを用いた開発は結構すんなりやれて使いやすかった印象。
importするパスが何とかなれば、もっと使いやすいんけどな。。。