A while back, Ned Batchelder, a well-known Python developer, posted a tweet on twitter that sparked a lively discussion:

Ned Batchelder twitter

That is, instead of using pip install, use python -m pip install to install the package. Both beginners and experienced developers encounter this problem. It can be confusing when you install a package using pip, but when you call it, it says you can’t import it: for newcomers you’ve probably read some old tutorials, for veteran developers you’re probably still used to the old way of using it. In fact, if you often read the official documentation, you will find that the official way has long been changed to python -m pip, so what would be the problem with using the old pip install?

To start with, my opinion is the same as Ned Batchelder’s, that python -m pip should be used whenever possible.

python -m modname

Let’s start with this usage, which is actually available in the Python standard library. It’s the equivalent of importing a module from the command line and performing some default behavior, and there’s really no trick to it, as long as the main function is defined in the package.

A few common examples are:

  1. python -m http.server. start a simple HTTP server.
  2. echo ‘{1.2:3.4}’ | python -m json.tool. formatting json data output on the command line.
  3. python -m venv venv. Create a virtual environment directory.
  4. python -m webbrowser https://google.com. Open a browser to access https://google.com.
  5. python -m flask run. Start the Flask application.

Of course you can add more arguments, as long as the main function can be parsed inside.

Problems with pip install

First, as a matter of engineering practice, I don’t install packages into the global Python environment unless necessary, and every project should reasonably use a virtual environment for development.

In my case, I have a Python 2.7 and a Python 3.X version by default on a new install, but as time goes by, I keep updating the Python version, and sometimes I download the latest version from the website and compile and install it just to try it out. This leaves a variety of Python versions on the computer over time.

Normally, using pip install or python -m pip install in an active virtual environment works exactly the same, but there are some scenarios where this is a problem. For example, I’m on a computer that is exiting a virtual environment, and python and pip are not the same:

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

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

I’ve forgotten exactly why I did this. But after I switched to python -m pip install, it didn’t matter. Because python -m pip ensures that the package you want to install will be in the same environment as the current interpreter.

pip version issues

One more point where you should use python -m pip install is the version of pip. In the early days I tried pipX to install packages this way, and I currently have the following versions on my computer:

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

There’s no need to get hung up on the pip2 series, since it’s Python 2.7 and you don’t install multiple minor versions (e.g. 2.7.9, 2.7.10) anyway. But the pip3 series is interesting. I have a 3.7 and a 3.9 version here, so which environment does pip3 refer to? There is no other way than to use “ll which pip3” to see the path.

Of course it’s more obvious which environment I’m installing packages for with pip3.7 or pip3.9, but here’s a hidden problem: if I compile a Python3.9.1 and a Python3.9.3, how do I tell the difference? Using python -m pip is a painless solution: I’ll use the pip installation from whichever Python interpreter you’re using.

A little tip

If you’re already used to the usage, you can set an alias and use :

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