pip installs a specific version when you put == and the version number after the package name. The same command downgrades or upgrades whatever’s already installed:
python -m pip install tabulate==0.9.0
I tested every command below in a real Windows Command Prompt with Python 3.12.5 and pip 24.2, inside a separate environment so you can see each install happen from scratch.
You’ll also see how to install a version range, find out which versions exist, pin versions in requirements.txt, and install straight from a GitHub tag.
pip install a specific version with ==
== pins an exact version. Here it is going into an environment that doesn’t have the package yet, followed by a check of what got installed:
from importlib.metadata import version
print("tabulate", version("tabulate"))
Command Prompt output:
Collecting tabulate==0.9.0
Downloading tabulate-0.9.0-py3-none-any.whl.metadata (34 kB)
Downloading tabulate-0.9.0-py3-none-any.whl (35 kB)
Installing collected packages: tabulate
Successfully installed tabulate-0.9.0
tabulate 0.9.0
importlib.metadata confirms it.The long path at the start is just the environment’s own Python. On your machine, python -m pip install tabulate==0.9.0 does the same thing.
I use python -m pip rather than bare pip so the package lands in the Python I’m actually running. ModuleNotFoundError after pip install shows what goes wrong otherwise.
How to downgrade a package with pip
There’s no separate downgrade command. Ask for an older version with ==, and pip uninstalls the newer one first:
python -m pip install tabulate==0.9.0 # from 0.10.0 back to 0.9.0
If pip says the requirement is already satisfied but the package seems broken, add --force-reinstall to install that version again from scratch.
pip install a version range: >=, <, ~= and !=
Often you don’t need one exact version, just one that’s new enough and not too new. Put the range in quotes:
from importlib.metadata import version
print("tabulate", version("tabulate"))
Command Prompt output:
Collecting tabulate<0.11,>=0.10
Downloading tabulate-0.10.0-py3-none-any.whl.metadata (40 kB)
Downloading tabulate-0.10.0-py3-none-any.whl (39 kB)
Installing collected packages: tabulate
Attempting uninstall: tabulate
Found existing installation: tabulate 0.9.0
Uninstalling tabulate-0.9.0:
Successfully uninstalled tabulate-0.9.0
Successfully installed tabulate-0.10.0
tabulate 0.10.0
| Specifier | Means | Example |
|---|---|---|
== | Exactly this version | tabulate==0.9.0 |
>=, < | At least, or below | "tabulate>=0.10,<0.11" |
~= | Compatible release: same minor series | tabulate~=0.9.0 means 0.9.x |
!= | Anything except this version | "tabulate!=0.10.0" |
==1.2.* | Any patch release of 1.2 | "tabulate==0.9.*" |
Combine conditions with a comma, and always quote anything containing < or >. The next section shows why.
Why pip install package>=version does nothing on Windows
In Command Prompt, > isn’t part of the version: it means “send the output to a file”. So an unquoted range quietly writes pip’s output to a file and installs nothing new:
from importlib.metadata import version
print("tabulate", version("tabulate"))
Command Prompt output:
Requirement already satisfied: tabulate in c:\pyguides\pin_env\lib\site-packages (0.9.0)
tabulate 0.9.0
0.10, and tabulate still on 0.9.0.Command Prompt treated = as a separator, so the file is named 0.10. pip only saw tabulate, which was already installed.
Bash and zsh on macOS and Linux misread > the same way. Wrap the requirement in double quotes and it works everywhere.
How do I see which versions of a package are available?
pip index versions lists every version on PyPI and marks the one you have. It’s still labeled experimental, but it works well:
from importlib.metadata import version
print("tabulate", version("tabulate"))
Command Prompt output:
WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning.
tabulate (0.10.0)
Available versions: 0.10.0, 0.9.0, 0.8.10, 0.8.9, 0.8.8, 0.8.7, 0.8.6, 0.8.5, 0.8.4, 0.8.3, 0.8.2, 0.8.1, 0.8.0, 0.7.7, 0.7.5, 0.7.4, 0.7.3, 0.7.2, 0.7.1, 0.7, 0.6, 0.5.1, 0.5, 0.4.4, 0.4.3, 0.4.2, 0.3
INSTALLED: 0.9.0
LATEST: 0.10.0
ERROR: Invalid requirement: 'tabulate==': Expected end or semicolon (after name and no valid version specifier)
tabulate==
^
INSTALLED: 0.9.0. The old tabulate== trick now fails.You may have seen an older trick: pip install tabulate== with nothing after it, which used to print the versions in its error. Current pip rejects it as an invalid requirement, so use pip index versions instead.
Check which version of a package is installed
Any of these works. The first two run in the terminal, the last one inside your Python code:
python -m pip show tabulate # the Version: line
python -m pip list # every installed package
from importlib.metadata import version
print(version("tabulate"))
Many packages also expose __version__, as checking the pandas version shows, but importlib.metadata works for every installed package.
Pin versions in requirements.txt
For a project, put the versions in requirements.txt so everyone, and every server, installs the same ones:
tabulate==0.9.0
Command Prompt output:
Collecting tabulate==0.9.0 (from -r requirements.txt (line 1))
Downloading tabulate-0.9.0-py3-none-any.whl.metadata (34 kB)
Downloading tabulate-0.9.0-py3-none-any.whl (35 kB)
Installing collected packages: tabulate
Successfully installed tabulate-0.9.0
tabulate==0.9.0
pip install -r reads the file. pip freeze prints installed versions in the same format.Running python -m pip freeze > requirements.txt writes your current versions to the file. Do it inside a virtual environment, or you’ll capture every package on your machine.
Install a specific version of a package from GitHub
When a version isn’t on PyPI, or you need an unreleased fix, install from the repository with git+https and pin a tag, branch or commit after @:
python -m pip install "git+https://github.com/astanin/python-tabulate.git@v0.9.0"
# a branch or a commit works the same way
python -m pip install "git+https://github.com/owner/repo.git@main"
python -m pip install "git+https://github.com/owner/repo.git@1a2b3c4"
This needs Git installed. I installed tabulate 0.9.0 from its GitHub tag this way, and it worked; I left out the screenshot only because pip prints a temporary folder from my user profile.
Downloading the same tag as a ZIP archive failed to build, because tabulate works out its version from Git history. If a ZIP install fails like that, switch to git+https.
pip install specific version: quick reference
| Goal | Command |
|---|---|
| Exact version | python -m pip install tabulate==0.9.0 |
| Downgrade | Same as above, with the older version |
| Range | python -m pip install "tabulate>=0.10,<0.11" |
| Reinstall the same version | python -m pip install --force-reinstall tabulate==0.9.0 |
| See available versions | python -m pip index versions tabulate |
| See the installed version | python -m pip show tabulate |
| From a file | python -m pip install -r requirements.txt |
| From a GitHub tag | python -m pip install "git+https://github.com/owner/repo.git@v1.0" |
Related guides on installing and checking Python packages:
- ModuleNotFoundError after pip install
- Virtual environments in Python
- Check your Python version
- Check the pandas version
- Upgrade TensorFlow to the latest version
Frequently asked questions
How do I install a specific version of a package with pip?
Use ==: python -m pip install tabulate==0.9.0. If a different version is installed, pip replaces it.