Pip not working

Hi there!
I’m having an issue with pip external command. In cmd I’ve done the py -m pip install -U pip command and it did work, though afterwards i tried to use pip --version command and pip install pyautogui command and both of these seem to not work. Appearantly ‘pip’ is not recognized as an internal or external command, operable program or batch file.

You need to add the Scripts directory to your path, as the warning message states.

The message that appears in yellow in your screenshot means exactly what it says, and directly explains the simplest fix for the issue. However, it is important to understand the issue fully - among other reasons, as a matter of taking back control of your computer from people who want to make your computer “easy to use” (in the ways that they can benefit from).

When you install Python versions on Windows with the default installer, it may not add that Python to your PATH environment variable depending on the installer settings (carefully examine the checkboxes when running the installer, and make sure you understand the purpose of each option).

Using python at the command line - just like any other program name - tries to find a corresponding executable (in this case, python.exe) in any of the places in the PATH, in order, and reports an error if nothing is found that way. Similarly for pip and for py. However, py will always be found, because it is placed in the Windows install directory, which is guaranteed to be on the PATH.

The purpose of py is to use its own logic to locate and choose a Python installation, instead of searching the PATH. This is why Windows installers give you the option not to put new Python versions on the PATH; it can be confusing to figure out which one will be chosen, and py offers more control, while also allowing the source files themselves to specify which Python to use (like how #! lines work on Unix-like operating systems; that’s a built-in feature there, but Windows doesn’t work that way).

Every Python installation potentially includes its own, corresponding Pip installation. The purpose of that Pip installation is to install third-party packages for that Python installation. Pip consists of both library code (which can be run using the -m flag for Python) and some wrapper executables (they just invoke the corresponding Python and tell it to run the library code) stored in a Scripts subfolder of the install directory.

The Scripts subfolder needs to appear separately in the PATH in order to be discovered; PATH entries don’t get searched recursively. The installer should add both paths to PATH when asked, but of course it’s also possible to configure PATH manually and this can easily get out of sync.

For current versions of Python, there are generally three such wrappers: pip.exe (of course, on other operating systems the equivalents might not have the .exe filename extension), pip3.exe and pip3.X.exe (with whichever minor version number; in your case pip3.11.exe). The idea is that pip can find whichever Python installation is first on the PATH, but pip3 will only find a 3.x installation, and pip3.11 will only find a 3.11 installation. But, of course, this is only a partial solution. For people who wanted to maintain a separate 2.x installation, they would have to make it appear earlier on the PATH in order for this scheme to actually be useful. (Then they would do the same with the Python folders, and type e.g. python to run 2.x and python3 to run 3.x.) But also keep in mind that nothing prevents having more than one Python 3.11 installation on the system!


Let’s sum up the implications for the behaviour of the commands.

  • By doing py -m pip, you install or update packages (including Pip itself) for the Python installation that was chosen by py - the same one that runs when you use py myscript.py.

  • By doing python -m pip, you install or update packages for the Python installation that is found using python (assuming one is found that way, and that Pip is available for it).

  • By doing pip, you typically but not necessarily install or update packages for the Python installation that is found using python (assuming that one is found that way, and that Pip is available for it). The pip wrapper executable should automatically find the “right” Python that it “belongs” with (as long as the installation is not seriously broken), but the PATH can be misconfigured such that this is a different Python from the one that python finds.

It kinda has to work that way. The alternative to having separate Pips is telling Pip which Python to install for, every time. Fortunately we don’t live in that universe.

Just like how you can use py -m pip install -U pip to upgrade the Pip that belongs to the Python that is found by py, you can use py -m pip install pyautogui to use Pip to install pyautogui for the Python that is found by py, or py -m pip --version to check the version of Pip that belongs to the Python that is found by py.


My strong personal recommendation is to bypass the PATH issue by using virtual environments. Once a virtual environment is set up, you don’t have to worry about

  • The PATH (it’s automatically reconfigured when you activate the environment, and restored when you deactivate it)
  • What operating system you’re on (you can use python for commands regardless, and it means the Python in the virtual environment - that’s the point of the path reconfiguration)
  • The --user option for Pip (since the virtual environment is personal to the user creating it, you always have access rights to install packages)
  • Pip not being available (if you create the virtual environment from a source that doesn’t have Pip, it will be bootstrapped into the virtual environment by default)
  • Messing up a Python installation that the system depends on (not applicable for Windows, but potentially serious for Linux systems that come with important system maintenance Python scripts pre-deployed - never use sudo with Pip!)
  • Library version conflicts between different projects (you can always just make a separate virtual environment for each project, and install specifically what that project needs)

They’re also vital for properly testing deployment of your own code as a library for others to use.

Yes, this does mean there are even more “installed Pythons” on your system, but seriously, it’s much easier to manage this way. The only real downside is the potential to waste a bit of disk space (amounts that most people would consider trivial these days).

On Windows, setting up a virtual environment might look like navigating to a folder where you want to put it, and then py -m venv my_venv (or whatever you want to call it). A corresponding my_venv subdirectory is created, which contains a virtual environment based off of the default Python found by py. (If you want a different Python, you can read the documentation for py and see how to choose it; or explicitly give the path to the Python whose venv module you want to use - this has the same setup that Pip does). From here, my_venv/scripts/activate.bat (there’s also a .ps1 script for Powershell) activates that virtual environment: the PATH is reconfigured, and the prompt changes to show that the virtual environment is active.

While active:

  • deactivate does exactly what it says on the tin. (The script is my_venv/scripts/deactivate.bat, but because of the PATH configuration, you don’t need to specify that.)
  • python means the Python of that virtual environment.
  • pip means the Pip of that virtual environment, and will install packages for that virtual environment.
  • py has its original meaning, and is probably not useful at the moment.

On Windows, note that *you still need python -m pip rather than just pip specifically when upgrading Pip. This is because upgrading Pip needs to replace the wrapper executable, so the running process can’t be that executable itself (Windows disallows this; other operating systems are fine with it last I checked).

1 Like