最近,Pipenvは市民権を得てきていて,入門記事をよく見かけるようになっているような気がしています.
ただ,pipenv uninstall
に比べてpipenv clean
が紹介されていないことが多い気もしていて,「正直pipenv clean
の方が便利じゃない?」と思っているので,その啓蒙です.
環境
多分クリティカルではないですが一応
- Python 3.6.8
- Pipenv 2018.11.26
pipenv uninstall
を常用することの問題点
パッケージの削除の仕方として,pipenv uninstall [package(s)]
が入門記事でよく紹介されていますが,このコマンドは依存関係を見ずに削除します.そのため,このコマンドを常用するのには少し問題があると思っています.
といってもわかりづらいと思うので,具体例を2つほど挙げてみます.
具体例1
1つ目は,pipenv uninstall
しても,そのパッケージが依存しているライブラリは(ローカルでは)削除されないということです.
例えば以下のように,pipenv install
して,pipenv uninstall
しても,scikit-learnの依存パッケージである,joblibやscipyは削除されずに残ってしまいます.
$ pipenv install scikit-learn
$ pipenv uninstall scikit-learn
$ pipenv graph
joblib==0.13.2
scipy==1.3.1
- numpy [required: >=1.13.3, installed: 1.17.2]
とはいえ,Pipfile.lock
は以下のように,ちゃんと綺麗になっているので,チーム開発をしていて他者に影響を与えることはありません.
自分は変に潔癖なのでこの辺り大変気になるのですが,気にならない人は気にならないと思います.
{
"_meta": {
"hash": {
"sha256": "415dfdcb118dd9bdfef17671cb7dcd78dbd69b6ae7d4f39e8b44e71d60ca72e7"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {},
"develop": {}
}
具体例2
こちらの方が重要だと思いますが,他パッケージがそれに依存していても消せてしまう点です.
例えば,以下のような感じです.
$ pipenv install scikit-learn numpy
$ pipenv uninstall numpy
$ pipenv run python3 -c 'import sklearn'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/yuma/.local/share/virtualenvs/pipenv-mDs4mp0Y/lib/python3.6/site-packages/sklearn/__init__.py", line 76, in <module>
from .base import clone
File "/home/yuma/.local/share/virtualenvs/pipenv-mDs4mp0Y/lib/python3.6/site-packages/sklearn/base.py", line 13, in <module>
import numpy as np
ModuleNotFoundError: No module named 'numpy'
わざとらしく感じるかもしれませんが,同様なことをpytorchとnumpyで一回やらかしました.
流れとしては,
- 初めはnumpyを直接使う気でいたので,Pipfileに書いた.
- やっぱ使わないわ,(Pipfileから)消すか.
pipenv uninstall numpy
- uninstallされたので,当然
import torch
でエラー
まあこちらについても,Pipfile.lock
上はちゃんとnumpyも生きているので,自分が多少時間を取られるだけですが.
pipenv clean
とは
pipenv clean -h
すると,
Uninstalls all packages not specified in Pipfile.lock.
と表示される通り,Pipfile.lockに書かれていないパッケージを全て削除するコマンドです.Pipfile.lockが古いと,再ロックするようなので,pipenv clean
する前にPipfileを編集しておくことで,パッケージの削除が(多分安全に)行えます.
pipenv clean
を使うと
先に挙げた具体例で代わりにpipenv clean
を用いた場合を示します.
具体例1
以下のコマンド既に打った状態を想定します.
$ pipenv install scikit-learn
やることは,Pipfileのscikit-learnの行を削除して,pipenv clean
するだけです.
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
- scikit-learn = "*"
[requires]
python_version = "3.6"
するとちゃんと,依存パッケージも全て削除されます.
$ pipenv clean
Pipfile.lock (25c533) out of date, updating to (ca72e7)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (ca72e7)!
Uninstalling scipy…
Uninstalling scikit-learn…
Uninstalling numpy…
Uninstalling joblib…
$ pipenv graph
# なにも出ない
具体例2
同様に以下のコマンド既に打った状態を想定します.
$ pipenv install scikit-learn numpy
Pipfileのnumpyの行だけを削除して,pipenv clean
してみます.
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
scikit-learn = "*"
- numpy = "*"
[requires]
python_version = "3.6"
するとこちらでは,ちゃんと依存パッケージを見ているので,numpyは削除されずに残っていることがわかります.
$ pipenv clean 3079ms
Pipfile.lock (3b103b) out of date, updating to (25c533)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
✔ Success!
Updated Pipfile.lock (25c533)!
$ pipenv run python3 -c 'import sklearn; print(sklearn.__version__)'
0.21.3
まとめ
-
pipenv clean
のpipenv uninstall
に対する優位性を示した. - Pipenv詳しくないので,
pipenv clean
にも罠があるようなら教えていただければ幸いです.