前言

这几天知名 Python 开发者 Ned Batchelder 在 twitter 发了个推引发了热烈讨论:

Pic

就是说不要用pip install而是用python -m pip install安装包。无论是对于初学者还是老开发者都遇到这个问题,使用 pip 安装了包,但是调用时却显示无法导入,会让人很迷惑:对于新人来说很可能看了一些老旧的教程,对于老开发者可能还习惯过去的用法。其实如果经常看过官方文档就会发现,官方早就改成python -m pip的方式了,用旧的pip install会有什么问题呢?

先说结论,我的观点和 Ned Batchelder 是一样的,无论在何时都应该用python -m pip

python -m modname

先说一下这种用法,其实在 Python 标准库里有一些这样的用法。它相当于在命令行下就可以导入模块并执行默认的一些行为,其实也没有什么高深的技巧,只要包里面定义了__main__函数就可以。

举例几个常见的:

  1. python -m http.server。启动一个简单的 HTTP 服务器
  2. echo '{1.2:3.4}' | python -m json.tool。在命令行格式化 json 数据输出
  3. python -m venv venv。创建虚拟环境目录
  4. python -m webbrowser https://www.dongwm.com。打开浏览器访问对应网址
  5. python -m flask run。 启动 Flask 应用

当然还可以添加更多参数,只要 main 函数里面能够解析就可以。

pip install的问题

首先,按照我的工程实践,除非必要不要安装包到全局的 Python 环境中,每个项目都应该合理的使用虚拟环境开发。

就拿我来说,新装系统下,默认会有一个 Python2.7 和一个 Python3.X 的版本,但是随着时间流失,我会不断的更新 Python 的版本,有时候为了尝鲜我会从官网下载最新的版本然后编译安装。这样一段时间后电脑里就会留下各种 Python 版本。

通常来说,在激活的虚拟环境中使用pip install或者python -m pip install效果是完全相同的,但是有些场景下就有问题了。举个例子,我现在电脑在退出虚拟环境下,python 和 pip 就不是一套:

~/workspace
❯ python -m pip --version
pip 19.2.3 from /Users/dongwm/Library/Python/2.7/lib/python/site-packages/pip (python 2.7)

~/workspace
❯ pip --version
pip 19.1.1 from /Users/dongwm/lib/python2.7/site-packages/pip (python 2.7)

具体为什么搞成这样早就忘记了,但是在我改用python -m pip install这种方式后都无所谓了。因为python -m pip确保了想要安装的包会和当前解释器是一个环境。

pip 版本问题

还有一个应该用python -m pip install的点,就是 pip 的版本。在早期我曾经尝试过 pipX 这样的方式安装包,目前我的电脑有如下几个版本:

❯ pip
pip              pip2.7           pip3.7
pip2             pip3             pip3.9

pip2 系列的也没必要纠结,反正都是 Python2.7 也不会安装多个小版本 (例如 2.7.9, 2.7.10)。但是 pip3 系列就有意思了,我这里有个 3.7 和一个 3.9 的版本,那么 pip3 指的是哪个环境呢?除了用 "llwhich pip3" 看看路径以外是没有其他办法的:

❯ ll `which pip3`
lrwxr-xr-x 1 dongwm admin 36 Feb 16 22:15 /usr/local/bin/pip3 -> '../Cellar/python@3.9/3.9.10/bin/pip3'*

当然是用 pip3.7 或者 pip3.9 能更明显知道我在给哪个环境安装包,但这里有个隐藏的问题,假如我编译了一个 Python3.9.1 和一个 Python3.9.3,怎么区分呢?用python -m pip是一个省心的方案:你用哪个 Python 解释器,我就用它里面的 pip 安装。

一个技巧

如果你早已经习惯了就用法,可以设置个别名接着用:

❯ echo 'alias pip="python -m pip"' >> ~/.aliasrc

延伸阅读

  1. https://snarky.ca/why-you-should-use-python-m-pip/
  2. https://twitter.com/nedbat/status/1501564714442280967