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 bypy
- the same one that runs when you usepy myscript.py
. -
By doing
python -m pip
, you install or update packages for the Python installation that is found usingpython
(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 usingpython
(assuming that one is found that way, and that Pip is available for it). Thepip
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 thatpython
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 ismy_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).