98

I have a local version of Python 3.4.1 and I can run python -m pip install, but I'm unable to find the pip binary to run pip install. What's the difference between these two?

Rob Bednark
  • 22,937
  • 20
  • 77
  • 112
ilciavo
  • 2,569
  • 5
  • 23
  • 36

2 Answers2

83

2014

They do exactly the same thing. In fact, the docs for distributing Python modules were just updated to suggest using python -m pip instead of the pip executable, because it's easier to tell which version of python is going to be used to actually run pip that way.


Here's some more concrete "proof", beyond just trusting my word and the bug report I linked :)

If you take a look at the pip executable script, it's just doing this:

from pkg_resources import load_entry_point
<snip>
load_entry_point('pip==1.5.4', 'console_scripts', 'pip')()

It's calling load_entry_point, which returns a function, and then executing that function. The entry point it's using is called 'console_scripts'. If you look at the entry_points.txt file for pip (/usr/lib/python2.7/dist-packages/pip-1.5.4.egg-info/entry_points.txt on my Ubuntu machine), you'll see this:

[console_scripts]
pip = pip:main
pip2.7 = pip:main
pip2 = pip:main

So the entry point returned is the main function in the pip module.

When you run python -m pip, you're executing the __main__.py script inside the pip package. That looks like this:

import sys
from .runner import run

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

And the runner.run function looks like this:

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()

As you can see, it's just calling the pip.main function, too. So both commands end up calling the same main function in pip/__init__.py.

Kalanos
  • 3,922
  • 3
  • 37
  • 63
dano
  • 85,685
  • 13
  • 213
  • 211
  • Thanks for the answer, where can I corroborate that info? And where are the packages installed using the local Python? – ilciavo Sep 09 '14 at 20:11
  • 2
    And this "concept" does not only apply to `pip`, but also other Python "command line tools" can be called like this. E.g., `python -m markdown`. To quote from the python help menu `-m mod : run library module as a script` –  Sep 09 '14 at 20:57
  • 3
    @ilciavo: small correction: `python -m pip` runs `pip/__main__.py` module, not `pip/__init__.py`. It is a general rule: `python -m module` runs `module.__main__` module if `module` is a package (has `__path__` attribute) otherwise it runs the `module` itself -- both with `__name__=="__main__"`. – jfs Sep 09 '14 at 21:10
  • @J.F.Sebastian Yes, you're right. I've corrected that in my answer. – dano Sep 09 '14 at 21:14
  • For some reason if I try doing `python2.6 -m pip install` I get `/usr/bin/python: pip is a package and cannot be directly executed` – ilciavo Sep 09 '14 at 21:49
  • @ilciavo Can you `import pip` at all when you run `python2.6`? – dano Sep 10 '14 at 00:27
  • Yes I can `import pip` but I can't `python -m pip install` on python 2.6 – ilciavo Sep 10 '14 at 05:32
  • 1
    @ilciavo Looks like that is a limitation of Python 2.6. It doesn't support using packages with the `-m` flag. You'll have to use `python -m pip.__main__` directly. – dano Sep 10 '14 at 15:05
  • @jfs just for clarification, `python -m module` runs both `module/__init__.py` and `module/__main__.py` if the `module` is a package. – starriet Sep 18 '21 at 07:55
  • @starriet: it imports the module (`__name__ == "module"`) but it doesn't run it. For comparison, `-m package` does run `package/__main__.py` -> `__name__ == "__main__"`). btw, `-m module` likely imports other modules too (add `-v`, to see them). – jfs Sep 18 '21 at 13:06
  • @jfs I mentioned `-m package`, not import. `-m package` runs both `__init__.py` and `__main__.py`, doesn't it? – starriet Sep 19 '21 at 00:08
  • @starriet: `-m package` does not "run" `__init__.py` that you can see by inspecting `__name__` (if you see `__main__` then the code is "running" if you see (for the exact same module, exact same module) just its name then it is just an import. – jfs Sep 23 '21 at 17:27
21

2021

This only happens if you create the venv with PyCharm. Please check if Scripts/pip-script.py located in your virtual environment

pip install and python -m pip install -- is not really the same. Or welcome back into the HELL of VERSIONING & DEPENDENCIES :-(

I was used to type pip(.exe) install <name> if I want install a package. But I run into trouble, if I try to install package Pillow. It breaks every time with an error message.

Today I retry python -m pip install copy&pasted from the manual and it works. Before I ignored it and type pip.... Because I thought it is the same.

I start to dive a little bit deeper into pip and I find this question/answer. After a while I found that pip.exe calls the script <virtual-environment/Scripts>pip-script.py.

I fighting with the installation of package 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')()
    )

I was a little bit surprised that pip.exe still use the old version 19.0.3 of the package and not the new installed version 21.0.1.

I changed the two version strings by hand to 21.0.1. And now pip.exe was able to install Pillow proper.

From now I understand why pip still complains that I use an old version of pip.

enter image description here

I think the old v19 pip has problem to detect the supported platform and therefore sources instead of binaries are installed.

Andreas
  • 235
  • 2
  • 6
  • 1
    The highest voted answer backs up the answer concrete examples. To disagree with the poster would be more compelling if you built a more concrete case- your example of Pillow seems to be a tangent to answering the question at hand. Would using `python -m pip` have solved the Pillow issue? Thanks for contributing! – Allen M Feb 26 '21 at 02:00
  • 1
    @AllenM Thank you for your answer. I investigate again and I found out that pip-script.py is coming from PyCharm if I create a virtual environment with it. If I create the venv with command-line (python -m venv venv) this script missing in folder Scripts. – Andreas Apr 15 '21 at 06:44