What's the difference between `python -m pip <args>` and `pip <args>`?

  • on MS-Windows, pip.exe is an executable binary;
  • on GNU/Linux, pip is usually a Python script.

It seems that pip has subtle differences on different platforms?
Should I always use python -m pip <args> instead of pip <args> to avoid this inconsistency? :slightly_smiling_face:

I recommend using python -m pip (depending on the situation, py -m pip will make more sense on Windows), but it’s not “so that it works the same way on both Linux and Windows”. Instead, it’s because each platform has its own issues, and in both cases python -m pip works better overall. Unfortunately, there’s a lot to explain here.

When you use pip.exe on Windows, or pip on Linux, you run a program that will start up the Python runtime and use it to import the pip third-party package. On Linux the “program” is a shell script. On Windows it’s an executable binary. I don’t know offhand, whether pip.exe will spawn a python.exe subprocess, use a Python DLL, or just what.

Windows uses an executable binary because Windows does not have any concept of an executable script (text file). On Linux you can put Python code in a file named pip (and don’t need to give it a .py extension), start it off with a proper shebang line e.g. #!/usr/bin/env python (although Pip will instead use a specific, full path for the Python it came with) and set chmod +x, and the operating system will do the rest. On Windows, the best you can do is associate the .py extension with a Python interpreter; but then every Python file will use that interpreter. That’s not good enough, because the whole point is to have a separate Pip for each Python, so that you can install separate packages for each Python.

Using python -m pip is recommended because, as long as everything is setup properly, it will use the Pip that belongs to which ever Python python means. If that’s the wrong Python, you can choose a path to the right Python (or set the PATH, use virtual environments, use the py program instead on Windows to choose a Python, etc. etc.). If you use pip directly, it will use the Pip that is found first on the PATH, which could belong to a different Python. So it’s harder to get it right.

If you install multiple versions of Python on Linux, and don’t use virtual environments, it’s very easy to end up with only one pip script. That’s because when you “install” things on Linux, it wants to put all the executables side by side in /usr/bin. There isn’t a separate folder for each Python, so the pips can collide with each other. On Windows, you get a separate subfolder in Program Files (or similar folders) for each program. That’s better for maintaining separate pip.exes, but it causes a huge headache with maintaining the PATH. (This is a big part of why py exists.)

There is one extra reason to use python -m pip on Windows. That is: if pip.exe is running, Windows will not allow replacing the pip.exe file on disk. This means that pip install --upgrade pip can’t work. But python -m pip install --upgrade pip (or py -m pip install --upgrade pip) can work, because now python.exe is running instead.