"pip install"和"python -m pip install"之间有什么区别?

138
我有一个本地版本的Python 3.4.1,我可以运行python -m pip install,但是我找不到pip二进制文件来运行pip install。这两者有什么区别?
4个回答

104
它们做的事情完全一样,假设pip使用的是与python可执行文件相同的Python版本。分发Python模块的文档最近进行了更新,建议使用python -m pip代替pip可执行文件,因为它允许您明确指定要使用的Python版本。在安装了多个Python版本的系统中,pip链接到哪个版本并不总是清楚的。
这里有一些更具体的“证据”,证明这两个命令应该做同样的事情,不仅仅是相信我的话和我链接的错误报告 :)
如果你看一下pip可执行脚本,它只是做了这个:
from pkg_resources import load_entry_point
<snip>
load_entry_point('pip==1.5.4', 'console_scripts', 'pip')()

它调用{{link1:load_entry_point}},该函数返回一个函数,然后执行该函数。它使用的入口点称为'console_scripts'。如果你查看pip的entry_points.txt文件(在我的Ubuntu机器上是/usr/lib/python2.7/dist-packages/pip-1.5.4.egg-info/entry_points.txt),你会看到这个内容:
[console_scripts]
pip = pip:main
pip2.7 = pip:main
pip2 = pip:main

所以返回的入口点是pip模块中的main函数。
当你运行python -m pip时,你实际上是在执行pip包内的__main__.py脚本。它的内容如下:
import sys
from .runner import run

if __name__ == '__main__':
    exit = run()
    if exit:
        sys.exit(exit)

而且runner.run函数看起来像这样:
def run():
    base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ## FIXME: this is kind of crude; if we could create a fake pip
    ## module, then exec into it and update pip.__path__ properly, we
    ## wouldn't have to update sys.path:
    sys.path.insert(0, base)
    import pip
    return pip.main()

正如你所看到的,它只是调用了pip.main函数。因此,这两个命令最终都会调用pip/__init__.py中的相同main函数。

3
这个“概念”不仅适用于 pip,其他 Python 的 “命令行工具” 也可以这样调用。例如:python -m markdown。引用 Python 帮助菜单中的一句话:“-m mod : 将库模块作为脚本运行”。 - user2489252
4
@ilciavo指出一个小问题:python -m pip 实际运行的是 pip/__main__.py 模块,而不是 pip/__init__.py。一般情况下,如果一个模块是一个包(有__path__属性),那么 python -m module 命令会运行 module.__main__ 模块,否则它会直接运行这个 module 模块本身,都会以 __name__=="__main__" 的形式运行。 - jfs
2
@ilciavo 看起来这是 Python 2.6 的一个限制。它不支持使用 -m 标志与包一起使用。你必须直接使用 python -m pip.__main__ - dano
只有在设置成那样的情况下,它们才会做同样的事情。可能会出现混乱的设置,其中pip在不同的解释器中运行,而python所指的解释器不同。这就是为什么推荐使用python -m的原因。因此,您可以编辑第一段,改为说:“它们应该做完全相同的事情,文档...因为这样您就可以知道将使用哪个解释器...” - undefined
1
@wjandrea 感谢你的建议。我使用了不同的措辞,但我更新了我的回答,以明确他们只有在针对相同版本的Python时才会执行完全相同的操作。 - undefined
显示剩余9条评论

26

2021

只有在使用PyCharm创建虚拟环境时才会出现这种情况。请检查您的虚拟环境中是否存在Scripts/pip-script.py。

pip installpython -m pip install不是完全相同的。或者欢迎回到版本控制和依赖关系的地狱 :-(

我习惯于键入pip(.exe) install <name>来安装软件包。但如果我尝试安装Pillow软件包,就会遇到麻烦。它每次都会出现错误信息。

今天,我从手册中复制并粘贴了python -m pip install,然后它就可以用了。之前我忽略了它,直接键入了pip....因为我认为它们是一样的。

我开始深入研究pip,然后找到了这个问题/答案。过了一会儿,我发现pip.exe调用了脚本<virtual-environment/Scripts>pip-script.py。

我正在努力安装Pillow软件包。

#! .\venv\Scripts\python.exe
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3'
__requires__ = 'pip==19.0.3'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('pip==19.0.3', 'console_scripts', 'pip3')()
    )

我有点惊讶pip.exe仍在使用旧版19.0.3而不是新安装的版本21.0.1。

我手动更改了这两个版本字符串为21.0.1。现在pip.exe能够正确安装Pillow。

从现在开始我明白了为什么pip仍然抱怨我使用旧版pip。

enter image description here

我认为旧版的v19 pip无法检测支持的平台,因此会安装源码而不是二进制文件。


2
最高票答案用具体的例子支持了答案。如果你能提出更具体的论据来反驳发帖者,那会更有说服力——你关于Pillow的例子似乎是离题了。使用python -m pip是否可以解决Pillow问题?感谢您的贡献! - Allen M
2
@AllenM 谢谢你的回答。我重新调查了一下,发现如果我使用PyCharm创建虚拟环境,pip-script.py就会出现。但是,如果我使用命令行(python -m venv venv)创建venv,则该脚本在Scripts文件夹中缺失。 - Andreas

9
每次安装 Python 都可能附带自己的 Pip 版本。 (某些安装可能会出于安全原因有意排除 Pip:例如,当将 Python 包含在 Linux 发行版中时,通常会省略 Pip,以便用户不会无意中在操作系统依赖的 Python 副本中安装有害内容。)
从概念上讲,Pip 由两个部分组成:pip 标准库模块,包含在 pip.py 文件中; 以及 pip “包装器”可执行文件。(在 Windows 上,这实现为一个实际的 .exe 文件;在 Mac 和 Linux 上,它应该只是一个具有执行权限设置且没有 .py 文件扩展名的 Python 脚本)。包装器的目的是运行相应标准库模块中的“主”代码。
在命令行上使用 pip 将查找并运行 PATH 环境变量中首先出现的任何包装器可执行文件,然后运行与该包装器关联的 Python 安装的相应代码。 因此,它将为任何 Python 安装安装第三方库。

在命令行中使用python -m pip将查找并运行PATH环境变量中第一个Python,并指示其在其标准库中查找pip标准库模块(不是直接查找;它将像任何模块导入一样搜索sys.path)并将其“作为模块”运行。因此,它将为在PATH中找到的Python安装第三方库。

在Windows上,在命令行中使用py -m pip将(除非系统配置严重错误)查找并运行{{link2:py可执行文件}},该文件安装在始终位于PATH上的Windows目录中。这反过来会{{link3:使用自己的逻辑}}选择系统上的Python,运行pip,然后从那里继续进行。

根据系统配置的不同,这些命令可能不会选择相同的Python安装程序

使用 python -m pip 确保为 使用 python myscript.py 运行的同一Python 安装程序安装库。对于那些编写了 myscript.py ,需要该代码使用将被安装的库并希望它能够在任何 python 中运行的人来说,这非常有用。

对于 Windows 特别说明,pip install --upgrade pip 不起作用这是因为升级 Pip 需要替换磁盘上的 Pip 包装器可执行文件;通过以这种方式运行命令,该包装器可执行文件 是正在运行的程序,而 Windows 不允许程序在磁盘上替换自己。通过使用 python -m pip install --upgrade pippy -m pip install --upgrade pip,可以避免这个问题,因为现在包装器可执行文件不会运行 - Python(可能还有 py)运行,使用来自 pip.py(或缓存的 pip.pyc)文件的代码。


感谢您更新并提供有关Windows的详细信息。 - ilciavo
1
有一个小问题:pip不是标准库 - Cameron Bieganek

0

python -m pip:以python脚本的形式运行pip模块

pip:运行pip可执行文件

通常这两者会一起安装,并指向同一个python脚本。所以在大多数情况下,您可以使用任一形式的命令,它们会达到相同的结果。然而,使用python -m pip可以确保库被安装到与运行python <script.py>相同的Python实例中。如果在虚拟环境中,这将是由"activate"命令设置的Python版本。某些虚拟环境可能会或可能不会为pip设置新的路径。因此,通常最好明确使用python -m pip

如果您想测试以确保它们在您的路径上被正确找到:

Windows:

where python
where pip

Linux:
which python
which pip

注意:venv还会为激活的环境设置pip的路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接