前两篇分别学习了 Python 如何进行依赖的管理,以及结合虚拟环境来使用 pip 进行依赖管理。而有人觉得把 virtualenv 与 pip 分开来操作太麻烦了,而且 requirements.txt 描述依赖的方式十分笨拙,所以在前两者之上创建了 pipenv, 也谈不上重新发明了轮子吧。
3. Pipenv: 新一代依赖管理与虚拟环境
倘若不是经由 virtualenv, venv 而来到 pipenv,没有对比也就无法体会到 pipenv 的妙处的。pipenv 在总结了 virtualenv/venv 的缺点之后由 Kenneth Reitz 于 2017 年 1 月发布的新型 Python 依赖管理器。
它不再需要单独用 virtualenv 和 pip,只要一条命令 pipenv 完成所有的事
不用手动管理 requirements.txt 文件,而是由 pipenv 自动维护 Pipfile 和 Pipfile.lock 文件
自动创建虚拟环境,并且虚拟环境与项目文件分离
更详尽的依赖图(例如 pipenv graph),像 mvn dependency:tree 那样显示依赖树
控制台下输出颜色更丰富
下面来体验体验 pipenv
3.1 安装 pipenv
pip3 install pipenv --user
安装完后如果直接执行 pipenv 命令,提示 pipenv 找不到,并且 pip3 也不能用了
vagrant@ubuntu-bionic:~$ pip3
Traceback (most recent call last):
File "/usr/bin/pip3", line 9, in
from pip import main
ImportError: cannot import name 'main'
这时候也许应该重启 shell 应用新的路径环境,因 pip 安装的命令会放到 ~/.local/bin 目录中。看 ~/.profile 文件
# set PATH so it includes user's private bin if it exists
if[-d"$HOME/.local/bin"];then
PATH="$HOME/.local/bin:$PATH"
fi
因为 pip 安装 pipenv 之前目录 /.local/bin 可能不存在,pipenv 安装之后在 /.local/bin 中多出了以下几个命令
easy_install easy_install-3.6 pip pip3 pip3.6 pipenv pipenv-resolver virtualenv virtualenv-clone
其中的 pip3 要替代 /usr/bin/pip3。重启 shell,pipenv 等命令将能使用。从 pipenv 所安装的命令也能看出 pipenv 实质是建筑在 virtualenv 和 pip 之上的壳。
Linux 下能也能通过 Linuxbrew 来安装 pipenv
sudo apt-get install linuxbrew-wrapper
brew install pipenv # 如果不能运行 pipenv 的话也考虑重启 shell 应用路径环境
Mac OS X 下也是用 brew install pipenv 安装。
3.2 使用 pipenv
使用过程先以一张图片直观的展现出来
下面再简单分解说明
3.2.1 创建虚拟环境
pipenv install
自动创建虚拟环境,并生成 Pipfile 和 Pipfile.lock 文件。如果已有相对应的虚拟环境则检查 Pipfile 中是否有更新,有新的依赖则下载安装。
3.2.2 激活虚拟环境
pipenv shell
从上图中也是 source 了相应虚拟环境的 bin/activate 文件,因为底层就是一个 virtualenv。进到虚拟环境后,通过对 $VIRTUAL_ENV 或 pipenv --env 查看到它相对应的虚拟环境不在当前目录中,而是分离到了 ~/.local/share/virtualenvs/demo-PtmYtcbd/ 中,这也使得项目本身更干净了。
3.2.3 安装依赖
pipenv install requrests
和创建虚拟环境类似,所以我们也可以一步到位的创建虚拟环境并安装指定的模块。由 sys.path 显示出的内容可知模块会安装到虚拟环境下的目录 ~/.local/share/virtualenvs/demo-PtmYtcbD/lib/python3.6/site-packages 下。
依赖安装后自动更新 Pipfile 文件。我们也可以手工编辑该 Pipfile 文件,加入更多的依赖,保存后再次运行 pipenv install 即下载安装指定的依赖。
3.2.4 显示依赖树
假设我们还用 pipenv install boto3 安装了 boto3,显示依赖树用命令
pipenv graph
3.2.5 移除依赖
pipenv uninstall boto3
相当于执行了 pip uninstall boto3。这时候我们查看 Pipfile 文件确实是移到了 boto3 = "*" 这一行,并且 boto3 也从 ~/.local/share/virtualenvs/demo-PtmYtcbD/lib/python3.6/site-packages 中删掉了。但是它所依赖的包依旧在,所以再次显示依赖树变成下面的样子
要想干净的清除或许得 botocore, s3transfer, docutils ..... 逐个干掉,但不实际。pipenv graph 并非解析 Pipfile 生成的,而是扫描虚拟环境中的 site-packages 获得的。
若要得到真实的依赖树,应该坚决的把虚拟环境删了,再生成,反正之前下载的依赖在本地有缓存的。命令如下
pipenv --rm
pipenv install
pipenv graph
3.2.6 退出虚拟环境
deactivate
因为本质上在执行 pipenv shell 时就是 source 了虚拟环境的 bin/activate 文件,所以退出方式与 virtualenv 是一样的。也能用 exit, 有时候 exit 后不进行换行。
3.2.7 其他功能
pipenv 支持不同的 Python 版本
pipenv --two
pipenv --three
pipenv --python 2.7.14
pipenv --python path/to/python
pipenv 支持不同的代码环境,在 Pipfile 可以分组 [dev-packages], [packages] 分别指定不同的依赖,比如 dev 时才需要的测试相关的模块。安装依赖的时候可以用 pipenv install --dev,这很像 npm
自定义的虚拟环境目录
假如在项目目录中创建一个 .venv 目录,那么运行 pipenv install 后虚拟环境就会创建到该 .venv 目录中,而不是在 ~.local/share/virtualenvs/ 目录下。
pipenv 支持 .evn 文件设定环境变量
不显式激活虚拟环境直接用 pipenv 命令在虚拟环境中运行代码,如 pipenv run python test.py
4. 结论
venv 和 virtualenv 基本可看成是同一个东西,只是使用格式上的不同。通常情况下我们统称为 virtualenv
pipenv 是 pip 与 virtualenv 的组合体,底层的实现仍然是后两者,所以使用 pipenv 最好对后两者要有一定的了解
确实,最佳的虚拟环境选择顺序应该是 pipenv -> venv(因为自带) -> virtualenv。pipenv 和 virtualenv 都能支持 Python 2 和 Python 3
研究了那么多依赖管理与虚拟环境,Python 还是没有一个比较趁手的分发打包工具。有时候不得不用最原始的 zip 命令