ずっと気になりつつ手を出せていなかったPipenv
をちゃんと試してみました。
pipenvのインストール・セットアップ
まずはインストールから
# python3 環境で試してみたいため
pip3 install pipenv
インストール後、作業ディレクトリに移動
# 使用するバージョンを厳密に指定する
pipenv --python 3.7.2
# 上記以外にも下記のようにアバウトな指定も可能
# Python 3を使う場合
# pipenv --three
# Python 2を使う場合
# pipenv --two
これでcurrentにPipfile
ができる。
cat Pipfile
で中身を見てみる
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
[requires]
python_version = "3.7"
pipenvを用いたライブラリのインストール
ためしにbeautifulsoup4
とrequests
をpipenv
を使ってインストールしてみる。
$pipenv install beautifulsoup4 requests
Installing beautifulsoup4…
Adding beautifulsoup4 to Pipfile's [packages]…
✔ Installation Succeeded
Installing requests…
Adding requests to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
✔ Success!
Updated Pipfile.lock (b65c9c)!
Installing dependencies from Pipfile.lock (b65c9c)…
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 7/7 — 00:00:01
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
cat Pipfile
で再度Pipfile
の中身を見てみる。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
beautifulsoup4 = "*"
requests = "*"
[requires]
python_version = "3.7"
packages
の中に追記されているのが分かる。
ちなみにバージョンを指定しないでインストールすると*
になるよう。
ただ、インストールしたバージョンについてはPipfile.lock
なるものが作られて、こちらで管理されるよう。
npm
でいうpackage-lock.json
、
yarn
でいうyarn.lock
、
bundler
でいうGemfile.lock
のようなものですね。
package.json
でいうdevDependencies
の仕組みもあって、例えば開発時にのみflake8
を使いたいってときは--dev
をつけて実行すれば良い。
$pipenv install --dev flake8
Installing flake8…
Adding flake8 to Pipfile's [dev-packages]…
✔ Installation Succeeded
Pipfile.lock (cbc640) out of date, updating to (b65c9c)…
Locking [dev-packages] dependencies…
✔ Success!
Locking [packages] dependencies…
✔ Success!
Updated Pipfile.lock (cbc640)!
Installing dependencies from Pipfile.lock (cbc640)…
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 12/12 — 0
Pipfile
にもdev-packages
として依存関係が追加されている。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
flake8 = "*"
[packages]
beautifulsoup4 = "*"
requests = "*"
[requires]
python_version = "3.7"
pipenv環境で依存ライブラリのインストール
使う場面としては、git
でclone
してきたものがpipenv
を使っている場合などに使用。
Pipfile.lock
の依存関係を見て、必要なライブラリをインストールしてくれる。
$pipenv install
npm
でいうnpm install
と同じもの。
requirements.txt で管理しているプロジェクトにPipenvを導入する場合
例えば下記のように requirements.txt
で管理されているプロジェクトがあったとする。
$cat requirements.txt
beautifulsoup4==4.8.1
requests==2.22.0
pip install
の場合は下記のように実施して依存ライブラリをインストールすることになるが、
pip install -r requirements.txt
pipenv
を導入する場合は、上に書いた通りのコマンド(下記を参照)を実施すれば、勝手に依存ライブラリを認識してPipfile
を作成してくれる。
pipenv --python 3.7.2
上のコマンドを叩いた際に、下記のようなログも一緒に流れて、Pipfileに変換してくれたことが分かる。
requirements.txt found, instead of Pipfile! Converting…
✔ Success!
Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.
We recommend updating your Pipfile to specify the "*" version, instead.
実際に出力された Pipfile
は下記の通り。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
beautifulsoup4 = "==4.8.1"
requests = "==2.22.0"
[requires]
python_version = "3.7"
簡単にpipenv
への管理に移行できるのはとても良い。
pipenv環境での実行手順(shell)
ちなみにこの状態でpython3
を実行して下記のようにインストールしたpackageを読み込もうとするとエラーになる。
$python3
Python 3.7.2 (default, Feb 11 2019, 09:42:34)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'requests'
npm
とかだと、そのまま読み込めるところだけど、pipenv
はそうは行かないよう。
上に貼り付けたログにも出ていたが、pipenv shell
をすると、pipenvで作った環境内でshell
を起動できるようだ。
# shell起動
$pipenv shell
Launching subshell in virtual environment…
. /Users/username/.local/share/virtualenvs/dirname-85OFZKXi/bin/activate
~/dirname : $ . /Users/username/.local/share/virtualenvs/dirname-85OFZKXi/bin/activate
# 仮想環境がactivateされた状態となる
(dirname) ~/dirname : $python3
Python 3.7.2 (default, Feb 11 2019, 09:42:34)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> exit()
# 仮想環境から抜けるときはdeactivate
(dirname) ~/dirname : $deactivate
# 追記: 次回pipenv shell実行時にエラーが出るのでサブシェルも終了させる
~/dirname : $exit
サブシェルの終了について下記に追記しています。
pipenv shellをしても実行できないとき
pipenv環境での実行手順(ファイル実行)
試しにこんなスクリプト(sample.py
)を書いてみました。
無慈悲なコードですね。
import requests
print(requests)
これも当然ながらpython3 sample.py
と実行するとエラーになります。
$python3 sample.py
Traceback (most recent call last):
File "sample.py", line 1, in <module>
import requests
ModuleNotFoundError: No module named 'requests'
pipenv run python3 sample.py
で実行するようです。
$pipenv run python3 sample.py
<module 'requests' from '{省略}'>
独自のコマンドを定義する(scripts)
ちなみにpipenv run sample.py
と実行してみたら下記のようなエラーが出てきた。
$pipenv run sample.py
Error: the command sample.py could not be found within PATH or Pipfile's [scripts].
どうやら独自のコマンド定義ができるよう。
(package.json
内に書くscripts
みたいなやつ)
Pipfileに下記を追記する
[scripts]
sample = "python3 sample.py"
後は実行すればOK
$pipenv run sample
<module 'requests' from '{省略}'>
独自のコマンドに引数を渡す(scripts)
ちなみに定義したコマンドには引数も渡せるよう。
テストのためのスクリプト
import sys
args = sys.argv
print(args)
pipfileで下記のように定義
[scripts]
argvtest = "python3 argvtest.py"
引数を付けて実行してみると、ちゃんと引数を渡してくれている
$pipenv run argvtest AAAAAAA BBBBBBBBBB CCCCCCCCCCCCCCC
['argvtest.py', 'AAAAAAA', 'BBBBBBBBBB', 'CCCCCCCCCCCCCCC']
requirements.txtに書き出す
pipenv lock -r
を実行すると、依存関係にあるパッケージがrequirements.txt
形式で吐き出される。
$pipenv lock -r
-i https://pypi.org/simple
beautifulsoup4==4.7.1
certifi==2018.11.29
chardet==3.0.4
idna==2.8
requests==2.21.0
soupsieve==1.7.3
urllib3==1.24.1
ちなみにpipenv lock -r -d
を実行すると--dev
でインストールしたパッケージのみが表示される。
$pipenv lock -r -d
-i https://pypi.org/simple
entrypoints==0.3
flake8==3.7.5
mccabe==0.6.1
pycodestyle==2.5.0
pyflakes==2.1.0`
例えば開発依存も含めた状態でrequirements.txt
をエクスポートする場合は
pipenv lock -r > requirements.txt
pipenv lock -r -d >> requirements.txt
と打てばよいのかと思ったけど、そもそもpipenv
のやり方で環境構築すればいいわけだし、
使用用途してあるのは、開発依存は除外した状態でrequirements.txt
を作成するぐらいなのか
(ここらへん、実際どうなんでしょう?)
セキュリティの脆弱性の検知
下記コマンドで既知のセキュリティの脆弱性が無いか依存関係グラフを走査してくれるよう。
$pipenv check
Checking PEP 508 requirements…
Passed!
Checking installed package safety…
All good!
インストールしたパッケージをエディターで開く
コードリーディングしたい方にとっては便利かも
下記のコマンドを打つと、設定されているエディターでパッケージのディレクトリを開いてくれます。
(私の場合はvim
が起動してディレクトリが開かれる感じ)
pipenv open requests
環境変数:TODO
疲れたので、これは後で調べようと思います。
ドキュメントはここに書かれているようですね。
pipenv shellをしても実行できないとき
pipenv shell
をしてもShell for UNKNOWN_VIRTUAL_ENVIRONMENT already activated.
というメッセージが出てきて実行できないとき
pipenv shell
をすると下のようなエラーが出て、shellが実行できないときがあります。
(実際にはpipenv shell
をdeactivate
で終了させたあとに出てくるよう)
$pipenv shell
Shell for UNKNOWN_VIRTUAL_ENVIRONMENT already activated.
No action taken to avoid nested environments.
調べてみるとこのissueにたどり着きました。
pipenv shell, then deactivate should display warning #736
どうやらpipenv shell
は仮想環境でサブシェルを起動しているので、一度exit
でサブシェル自体を終了させないとこのようなエラーが出てしまうということらしい。
たしかにpipenv shell
って打つと下のようなメッセージが出てきていましたね。
Launching subshell in virtual environment…
個人的に混乱ポイントでしたので、備忘録がてら追記しました。
pipenv shell
で仮想環境を立ち上げたときは、最後にexit
でサブシェル自体も終了させるのをお忘れなきよう。
感想
npm
みたいに管理できるようになったのは嬉しいです。
特に今まではテストやフォーマット関連のライブラリも一緒くたに入れることになっていたので、それによる気持ち悪さがdev-packages
で解消できていたり、独自のコマンドも定義できるようになったので、開発もよりやりやすくなりそう。
ひとまず今後はPipenv
を基本使うようにしてみようと思います。
(どちらかというとPython触る機会自体は少ない自分ですが...😂)
参照資料
公式ドキュメント(日本語版)
https://pipenv-ja.readthedocs.io/ja/translate-ja/index.html
https://pipenv-ja.readthedocs.io/ja/translate-ja/advanced.html