A straightforward way to distribute desktop and command-line applications written in Python is to publish them on the Python Package Index (PyPI), which hosts hundreds of thousands of third-party packages. Many of these packages include runnable scripts, but using them requires decent familiarity with the Python ecosystem. With pipx
, you can safely install and execute such applications without affecting your global Python interpreter.
In this tutorial, you’ll learn how to:
- Turn the Python Package Index (PyPI) into an app marketplace
- Run installed applications without explicitly calling Python
- Avoid dependency conflicts between different applications
- Try throw-away applications in temporary locations
- Manage the installed applications and their environments
To fully benefit from this tutorial, you should feel comfortable around the terminal. In particular, knowing how to manage Python versions, create virtual environments, and install third-party modules in your projects will go a long way.
Note: If you’re a Windows user, then it’s highly recommended you follow our Python coding setup guide before plunging into this tutorial. The gist of it is that you should avoid installing Python from the Microsoft Store, as it could prevent pipx
from working correctly.
To help you get to grips with pipx
, you can download the supplemental materials, which include a handy command cheat sheet. Additionally, you can test your understanding by taking a short quiz.
Get Your Cheatsheet: Click here to download the free cheatsheet of pipx commands you can use to install and execute Python applications.
Take the Quiz: Test your knowledge with our interactive “Install and Execute Python Applications Using pipx” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Install and Execute Python Applications Using pipxIn this quiz, you'll test your understanding of how Python apps are run from isolated virtual environments using the pipx tool. With this knowledge, you'll be able to safely run Python apps that are installed globally in your operating system.
Get Started With pipx
On the surface, pipx
resembles pip
because it also lets you install Python packages from PyPI or another package index. However, unlike pip
, it doesn’t install packages into your system-wide Python interpreter or even an activated virtual environment. Instead, it automatically creates and manages virtual environments for you to isolate the dependencies of every package that you install.
Additionally, pipx
adds symbolic links to your PATH
variable for every command-line script exposed by the installed packages. As a result, you can invoke those scripts directly from the command line without explicitly running them through the Python interpreter.
Think of pipx
as Python’s equivalent of npx
in the JavaScript ecosystem. Both tools let you install and execute third-party modules in the command line just as if they were standalone applications. However, not all modules are created equal.
Broadly speaking, you can classify the code distributed through PyPI into three categories:
- Importable: It’s either pure-Python source code or Python bindings of compiled shared objects that you want to import in your Python projects. Typically, they’re libraries like Requests or Polars, providing reusable pieces of code to help you solve a common problem. Alternatively, they might be frameworks like FastAPI or PyGame that you build your applications around.
- Runnable: These are usually command-line utility tools like
black
,isort
, orflake8
that assist you during the development phase. They could also be full-fledged applications likebpython
or the JupyterLab environment, which is primarily implemented in a foreign TypeScript programming language. - Hybrid: They combine both worlds by providing importable code and runnable scripts at the same time. Flask and Django are good examples, as they offer utility scripts while remaining web frameworks for the most part.
Making a distribution package runnable or hybrid involves defining one or more entry points in the corresponding configuration file. Historically, these would be setup.py
or setup.cfg
, but modern build systems in Python should generally rely on the pyproject.toml
file and define their entry points in the [project.scripts]
TOML table.
Note: If you use Poetry to manage your project’s dependencies, then you can add the appropriate script declarations in the tool-specific [tool.poetry.scripts]
table.
Each entry point represents an independent script that you can run by typing its name at the command prompt. For example, if you’ve ever used the django-admin
command, then you’ve called out an entry point to the Django framework.
Note: Don’t confuse entry points, which link to individual functions or callables in your code, with runnable Python packages that rely on the __main__
module to provide a command-line interface.
For example, Rich is a library of building blocks for creating text-based user interfaces in Python. At the same time, you can run this package with python -m rich
to display a demo application that illustrates various visual components at your fingertips. Despite this, pipx
won’t recognize it as runnable because the library doesn’t define any entry points.
To sum up, the pipx
tool will only let you install Python packages with at least one entry point. It’ll refuse to install runnable packages like Rich and bare-bones libraries that ship Python code meant just for importing.
Once you identify a Python package with entry points that you’d like to use, you should first create and activate a dedicated virtual environment as a best practice. By keeping the package isolated from the rest of your system, you’ll eliminate the risk of dependency conflicts across various projects that might require the same Python library in different versions. Furthermore, you won’t need the superuser permissions to install the package.
Deciding where and how to create a virtual environment and then remembering to activate it every time before running the corresponding script can become a burden. Fortunately, pipx
automates these steps and provides even more features that you’ll explore in this tutorial. But first, you need to get pipx
running itself.
Test Drive pipx
Without Installation
If you’re unsure whether pipx
will address your needs and would prefer not to commit to it until you’ve properly tested the tool, then there’s good news! Thanks to a self-contained executable available for download, you can give pipx
a spin without having to install it.
To get that executable, visit the project’s release page on the official GitHub repository in your web browser and grab the latest version of a file named pipx.pyz
. Files with the .pyz
extension represent runnable Python ZIP applications, which are essentially ZIP archives containing Python source code and some metadata, akin to JAR files in Java. They can optionally vendor third-party dependencies that you’d otherwise have to install by hand.
Note: Internally, the pipx
project uses shiv
to build its Python ZIP application. When you first run a Python ZIP application that was built with shiv
, it’ll unpack itself into a hidden folder named .shiv/
located in your user’s home directory. As a result, subsequent runs of the same application will reuse the already extracted files, speeding up the startup time.
Afterward, you can run pipx.pyz
by passing the path to your downloaded copy of the file to your Python interpreter—just as you would with a regular Python script:
In addition to this, on macOS and Linux, you can use chmod
to make the file executable (+x
) and run it directly without specifying the python
command:
$ chmod +x pipx.pyz
$ ./pipx.pyz --version
1.4.3
This is made possible because of a shebang line included at the beginning of the ZIP archive, indicating the interpreter to run the file through. Even though it’s technically a binary file, the shell recognizes the shebang line before handing over the file to your Python interpreter.
You can pass command-line arguments and options to pipx.pyz
just as you would with the installed version of pipx
. For example, to install IPython into its own isolated environment, you can use this command:
Depending on which python
executable you choose to run the ZIP application, pipx
will base the virtual environment on that Python version.
A benefit of running pipx
as a self-contained Python ZIP application is that it won’t clutter your computer. On the other hand, it can get tedious after a while as you’ll need to specify its full path or locate the pipx.pyz
file and navigate to the parent directory each time. If you get tired of this nuisance, then it’s probably time to install pipx
on your system.
Install pipx
as a Standalone Tool
You’ve got several choices when it comes to installing pipx
on your computer, including an option to install pipx
through pipx
itself! This is not recommended, however, as it can lead to unexpected problems down the line.
Your next best option is to install pipx
using pip
. After all, the tool is available on PyPI as an ordinary Python package. That’s the most straightforward and reliable installation method, which will cause you the least amount of headaches. But, use it only when you don’t mind a few extra dependencies in your global Python interpreter, and never share it with other projects:
This always brings the tool’s latest release that should work out of the box. However, because pipx
ends up being installed as a Python module, you’ll need to invoke it by using the full python -m pipx
command. To use the plain pipx
command instead, you can configure Unix shell completions, as described in the next section.
Anyhow, the officially recommended way to get pipx
installed is through your operating system’s package manager, such as Scoop on Windows, Homebrew on macOS, or APT on Debian-based Linux distributions:
When you install pipx
as a system package, it becomes a standalone command that you can run from anywhere in your file system. At the same time, it may not be the most up-to-date release of pipx
, and you may end up installing a whole lot of additional dependencies, such as yet another Python interpreter.
It’s important to understand that installing pipx
as a system package ties it to the specific Python interpreter listed as a system package dependency, which may be obsolete. So, when you later install an application with pipx
, the tool will stick to whatever Python interpreter it came with to create a new virtual environment. But don’t worry. You’ll learn how to override this default choice when needed.
Configure pipx
Before the First Run
Regardless of whether you’ve installed pipx
or not, the first thing you must always do before you can use the tool to the fullest is to add the necessary folder paths to your PATH
environment variable. If you forget this step, then pipx
will remind you about it and provide a helpful message on the first occasion:
After successfully installing IPython, pipx
created two symbolic links to the ipython
and ipython3
executables in the associated virtual environment. Unfortunately, there’s currently no way to access those symlinks from your terminal because their parent folder isn’t listed on the PATH
variable.
To fix this, you can run the command suggested in the output message above and then reopen the terminal or reload your shell configuration:
On Windows, running pipx ensurepath
modifies your user’s %PATH%
environment variable. It appends a path to the home directory where pipx
stores the installed packages, virtual environments, and more.
If you’re on macOS or Linux, then running the same command will add the following entry at the bottom of your shell’s configuration file, such as .bashrc
or .zshrc
, located in your user’s home directory:
~/.bashrc
# ...
# Created by `pipx` on 2024-02-22 13:08:43
export PATH="$PATH:/home/user/.local/bin"
It has virtually the same effect as modifying the %PATH%
variable on Windows. The next time you try running pipx ensurepath
, it’ll detect that you’ve already run it and won’t add redundant entries to your shell configuration.
To reveal the directory paths used by pipx
on your computer, you can invoke the environment
subcommand:
It displays the folder paths specific to your platform, which you can override by specifying one or more environment variables listed at the top of the output. You can also override the path to your default Python interpreter and disable the use of emoji this way.
One last step, which is completely optional and only applicable to macOS and Linux, was hinted at by your first run of the ensurepath
subcommand. It encouraged you to consider adding shell completions for pipx
to your terminal. Run pipx completions
to get the relevant instructions for the most popular shell flavors:
$ pipx completions
Add the appropriate command to your shell's config file
so that it is run on startup. You will likely have to restart
or re-login for the autocompletion to start working.
bash:
eval "$(register-python-argcomplete pipx)"
(...)
For example, to enable the pipx
completions in Bash, you can add the highlighted line to your ~/.bashrc
configuration file and reload it:
$ echo 'eval "$(register-python-argcomplete pipx)"' >> ~/.bashrc
$ source ~/.bashrc
This will enable command auto-completion for pipx
in Bash. Additionally, if you installed pipx
as a Python package using pip
, then it’ll also create a symlink to the pipx
executable so that you can invoke it directly rather than as python -m pipx
.
Now that you have everything in place, you can start using pipx
to install and run Python applications in isolated environments.
Turn PyPI Into an App Marketplace
Leading technology companies, such as Apple and Google, popularized the idea of digital distribution of mobile apps through their platforms like the App Store and Google Play. Soon after, this concept spread over to other areas, including the Microsoft Store for Windows devices, Chrome Web Store for web browser extensions, and even open-source operating systems like Ubuntu with its Ubuntu App Center.
In contrast, the primary focus of the Python Package Index (PyPI) has traditionally been to host third-party Python libraries aimed at developers rather than end users. With the help of pipx
, you can transform PyPI into a sort of Python app store.
Note: From now on, some of the pipx
output will look the same on all operating systems, so you may occasionally see only the Unix-style code blocks when looking at a particular feature.
There are two ways in which you can use pipx
for that purpose, which you’ll explore now.
Run Single-Use Python Apps
Sometimes, you find an interesting Python package that looks promising and would like to give it a try. For example, you may have heard of Ruff as the new kid on the block. It’s a near drop-in replacement for Python’s traditional code linters and formatters, but because it’s written in Rust, it blows them out of the water in terms of performance. Additionally, it combines multiple tools into a single Swiss army knife.
Under normal circumstances, you’d have to follow the usual steps and create a virtual environment, install the package with pip
, and figure out how to run its entry points. Then, when you’re done working with that package, you might want to remove it or the associated virtual environment to clean things up. That sounds like a lot of hassle!
Fortunately, pipx
lets you check out executable Python scripts effortlessly. In particular, you don’t need to install Ruff into one of your existing projects to run the tool against your codebase:
$ pipx run ruff check .
main.py:1:8: F401 [*] `math` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.
The pipx run
command downloads the latest version of the requested package from PyPI and installs it into a temporary virtual environment behind the scenes. It then runs the specified command, ruff check .
, from within that virtual environment without ever touching your project’s dependencies. The command lints all files in the current directory.
To speed things up, pipx
stores such temporary virtual environments in a cached location that expires after two weeks. The next time you run the same application, pipx
will try to reuse the cached environment before downloading the package again.
Note: Use the --verbose
flag when you run the command to find out the exact location of the temporary virtual environment made by pipx
. To disable the cache, forcing the removal and recreation of the corresponding virtual environment, include the --no-cache
flag.
In this case, the name of the package and its entry point were identical. But what if the entry point was named differently, or there was more than one entry point to a Python package? Well, if that turns out to be true, then you can provide the name of the package as a requirement specifier using the --spec
option:
$ pipx run --spec httpie http --body ifconfig.co/country
Poland
This installs the HTTPie package and runs its http
entry point to get the message body of an HTTP response from ifconfig.co/country. You might use this online service to check if your VPN is working correctly, for instance.
The requirement specifier will also help you when you need to run a specific version of a Python package. Suppose you were going through the Real Python tutorial about dependency management with Poetry and wanted to run a concrete version of Poetry mentioned in the text to follow along. To reproduce the same environment, you can provide a more detailed specifier:
$ pipx run --spec 'poetry==1.1.11' poetry new your-project
The original tutorial was written with this version of Poetry in mind before we overhauled the text. Since this old release is no longer compatible with the latest Python interpreter, you’d need to override the defaults, for example, by specifying the PIPX_DEFAULT_PYTHON
environment variable accordingly. You’ll learn more about how to do this later.
Note: The installation instructions in Poetry’s documentation recommend using pipx
for installing this dependency manager.
The ability to specify a package version can be useful when you need to run the same tool in different versions to manage multiple projects simultaneously. But the requirement specifier is even more flexible, and lets you bring extra dependencies or run a command straight from a remote Git repository or a ZIP archive with the desired Python package:
$ pipx run --spec git+https://github.com/realpython/reader.git realpython
$ pipx run --spec \
https://github.com/realpython/reader/archive/refs/tags/1.1.2.zip \
realpython
These two commands run the Real Python feed reader, which downloads digests of the latest tutorials, video courses, and podcast episodes. The first command runs the realpython
script directly from the default branch in the corresponding GitHub repository, while the second one fetches the package from the given release archive. You can optionally include a specific branch name or a commit hash in the Git URL by appending it after the at sign (@
).
In fact, you can use pipx
to run a Python script from any remote URL or a local file as long as it has the .py
extension:
$ echo 'print("Hello, World!")' > hello.py
$ pipx run hello.py
Hello, World!
$ python -m http.server &>/dev/null &
$ pipx run http://0.0.0.0:8000/hello.py
Hello, World!
After creating the Hello, World! program, you use pipx run
to execute it. Then, you host your script using Python’s HTTP server and let pipx
download the Python source file before running it.
If your script requires third-party packages, then you can declare them in a specially-formatted comment, which must adhere to the inline script metadata syntax (PEP 723) at the top of the file:
hello.py
# /// script
# dependencies = [
# "rich==13.7.0",
# ]
# ///
from rich import print
print("[b]Hello, World![/b]")
When you run this script through pipx
, it’ll prepare a temporary virtual environment and install the listed dependencies. As a result, the printed text will appear in a bold font.
Using pipx run
is perfect when you have a particular use case for a one-off command but don’t want to concern yourself with virtual environments. On the other hand, if you anticipate regular use of a command, then you’ll want to install the associated Python package in a more persistent way, letting pipx
set up convenient aliases in your shell.
Install Python Apps Globally
Say you liked Ruff and decided to make it your default static code analysis tool for Python going forward. To install the corresponding Python package globally while keeping your system’s interpreter intact, you can use pipx
like so:
The pipx install
command creates an isolated virtual environment and installs the latest version of the specified package into it. While this may sound similar to running a package that you saw in the previous section, there are two important differences.
First, pipx
creates a permanent virtual environment in a slightly different location to avoid cache eviction. To drill down to this environment, you can show the pipx environment
or use the --verbose
flag. The virtual environment is named after the installed package rather than with an arbitrary sequence of hexadecimal digits.
Secondly, pipx
makes a symbolic link for every entry point it can find in the installed package. This lets you run those tools directly by typing their names in your terminal. So, after installing the latest version of ruff
from PyPI, pipx
registers a new global command, ruff
:
As long as the parent folder shown in the output above is on your PATH
variable, you can invoke ruff
from anywhere in your terminal. If not, then be sure to configure pipx
as described earlier.
Note: When you type ruff
at the command prompt, your shell will try to find a matching symbolic link and follow it to the respective executable in the isolated virtual environment created by pipx
. In this case, ruff
is a binary executable file compiled for your platform.
As mentioned earlier, many Python packages define multiple entry points associated with different actions. In such a case, pipx
will create a separate symlink for each of them. For example, the mypy
package bundles mypy
, a popular static type checker for Python, along with a few other tools, including mypyc
, a C extension module compiler:
After installing mypy
with pipx
, you can see a list of five globally accessible commands are brought to your terminal by this package.
On the other end of the spectrum, you’ll find Python packages that don’t define any entry points at all. It’s safe to say that they make up the majority of packages on PyPI. If you recall, pipx
won’t install such packages, showing the following message:
$ pipx install polars
No apps associated with package polars or its dependencies.
⮑ If you are attempting to install a library, pipx should
⮑ not be used. Consider using pip or a similar tool instead.
Sometimes, however, one or more transitive dependencies of a package may contain an entry point. That’s the case with pandas, which doesn’t have any entry points of its own but builds on top of NumPy that does:
NumPy provides the f2py
command, which is a Fortran-to-Python interface generator. If you’d like pipx
to install such applications of dependent packages, then use the --include-deps
flag:
You’ll now have the f2py
application installed in the virtual environment housing pandas.
The pipx install
command doesn’t have a --spec
parameter like the one exposed by pipx run
, where you could define your requirement specifier. Instead, when installing a package, you can provide the desired version constraint as part of the package name as if with the plain pip
command:
$ pipx install poetry==1.1.11
Note that you can have at most one virtual environment per package because pipx
names its virtual environments after the corresponding Python packages. To differentiate between a few versions of the same package, you may provide a custom --suffix
option, which is an experimental feature. Alternatively, you can overwrite an existing environment with a new version by using the --force
flag.
One thing to watch out for when running or installing applications with pipx
is that you may already have them elsewhere in your system. For example, they could be installed in your global Python interpreter, the currently activated virtual environment, or as a system package, to name a few. In that case, pipx
will give you a warning but continue anyway:
It’s always a good idea to check beforehand whether there are any shell aliases, symbolic links, or binaries on the PATH
variable that would interfere with pipx
.
Now that you know how to install command-line Python applications using pipx
, you may be wondering how to uninstall an application or clean up the associated virtual environment. Next up, you’ll learn how to properly manage the applications you installed with pipx
.
Manage Your Installed Apps
In this section, you’ll perform several application management tasks using pipx
. After you’ve installed one or more Python apps, you’ll want to list them, upgrade or downgrade their versions, and uninstall those you no longer need. These actions resemble how you manage standard Python packages with good old pip
.
List the Installed Apps
You don’t have to memorize the individual entry points of every installed Python package. At any given time, you can list the installed apps and their commands by typing pipx list
in your terminal:
The output of the command above shows the location of virtual environments managed by pipx
, a folder with symbolic links to the executable entry points, and a folder with manual pages serving as documentation that some packages provide.
Note: Here, only IPython specifies manual pages, as indicated by the highlighted line. To view them on a Unix-like operating system, such as macOS or Linux, type man ipython
at the command prompt and hit Q to exit afterward. Unfortunately, there’s no native browser for manual pages on Windows.
The remaining part of the output includes the installed packages, their versions, and the Python interpreter used by the associated virtual environment. Additionally, every package contains a list of commands that you can invoke in your terminal.
To only display packages and their versions, use the --short
flag:
$ pipx list --short
ipython 8.22.1
mypy 1.8.0
pandas 2.2.1
poetry 1.8.0
ruff 0.2.2
Each package has a dedicated virtual environment for exclusive use. To get more information about the underlying virtual environments, including resolved absolute paths, use the --json
switch instead:
$ pipx list --json
{
"pipx_spec_version": "0.1",
"venvs": {
"ipython": {…},
"mypy": {…},
"pandas": {…},
"poetry": {…},
"ruff": {
"metadata": {
"injected_packages": {},
"main_package": {
"app_paths": […],
⋮
"package_version": "0.2.2",
"pip_args": [],
"suffix": ""
},
"pipx_metadata_version": "0.3",
"python_version": "Python 3.12.2",
"venv_args": []
}
}
}
}
As the name implies, this gets you output in the JSON format, which is suitable for automation tasks and integrating pipx
with other tools in your workflow. Thanks to JSON’s machine-readable syntax, you can access details like package versions, their locations, and dependencies in a programmatic way.
Once you know which applications are installed on your system, you can run their commands or modify their virtual environments.
Upgrade Apps to Their Latest Versions
When you want to upgrade an existing Python package to its latest version using the regular pip
tool, you run the pip install
command with the --upgrade
flag. In contrast, when using pipx
, you can perform the equivalent action with the upgrade
subcommand:
$ pipx upgrade ruff
upgraded package ruff from 0.0.292 to 0.2.2 (location: /.../venvs/ruff)
$ pipx upgrade ruff
ruff is already at latest version 0.2.2 (location: /.../venvs/ruff)
This finds the corresponding virtual environment and uses the associated Python interpreter to run the python -m pip install --upgrade ruff
command under the surface. That’s convenient because you don’t have to find and manually activate the correct virtual environment yourself.
It’s also fairly straightforward until you have many packages installed in separate virtual environments with pipx
. Upgrading all of them by hand would amount to a lot of work. Fortunately, you can upgrade all packages to their latest versions in one go with the upgrade-all
subcommand:
$ pipx upgrade-all
upgraded package ruff from 0.0.292 to 0.2.2 (location: /.../venvs/ruff)
upgraded package poetry from 1.2.2 to 1.8.0 (location: /.../venvs/poetry)
upgraded package mypy from 1.6.1 to 1.8.0 (location: /.../venvs/mypy)
upgraded package ipython from 7.34.0 to 8.22.1 (location: /.../venvs/ipython)
upgraded package pandas from 2.1.1 to 2.2.1 (location: /.../venvs/pandas)
Running this command will ensure that you have the most recent versions of all installed packages.
What if you didn’t want to be on the cutting edge but merely upgrade a package to a specific version? Or maybe instead of upgrading a package, you wanted to downgrade it? You’ll find out how to achieve both goals in the next section.
Downgrade Apps to a Specific Version
There’s no counterpart command for downgrading packages installed through pipx
. When you try to install a specific version of a Python package that you’ve already installed before, pipx
will refuse to proceed. At the same time, it’ll point you in the right direction:
With pip
, you could provide the requirement specifier to downgrade a package, but not in pipx
. Instead, you need to pass the additional --force
flag to tell the tool it’s okay to modify an existing virtual environment:
The pipx
tool translates the --force
flag to --force-reinstall
and supplies it to pip
under the hood. This means that pip
will install packages again even if they’re already in their target versions.
Note: If you work with pipx
long enough, then you may stumble upon the pipx reinstall
or pipx reinstall-all
commands. While these two subcommands look similar to pipx install --force
, they work differently. Later, you’ll use them to upgrade Python within virtual environments.
Finally, when none of the package versions meet your expectations, it may be time to get rid of the package altogether and find an alternative.
Uninstall Apps and Virtual Environments
To remove a Python package along with its virtual environment managed by pipx
, you can run the aptly named uninstall
subcommand:
$ pipx uninstall ruff
uninstalled ruff! ✨ 🌟 ✨
It’ll also delete any related manual pages and symbolic links from your shell, so you won’t be able to use them anymore.
If you’d like to uninstall all packages in one step, then pipx
has you covered, too:
$ pipx uninstall-all
uninstalled poetry! ✨ 🌟 ✨
uninstalled mypy! ✨ 🌟 ✨
uninstalled ipython! ✨ 🌟 ✨
uninstalled pandas! ✨ 🌟 ✨
$ pipx list
nothing has been installed with pipx 😴
Now, you can start from a clean slate all over again! Just be careful with this command if you have many tools installed with pipx
that you use on a regular basis, as it can take some time to bring them back.
Take Control Over Virtual Environments
Over the next few sections, you’ll learn how to modify the virtual environments managed by pipx
. Along the way, you’ll review a few practical use cases that you may encounter in your development workflow.
Inject Dependencies Into Managed Environments
The main advantage of using pipx
over pip
is that it manages virtual environments for you to ensure proper isolation of the installed packages. On the one hand, pipx
provides convenience and a safety net, but on the other hand, it seemingly prevents you from fiddling with the managed virtual environments. Sometimes, though, you might wish you had a degree of control over those environments.
For example, if you installed Poetry using pipx
, which is what the official documentation recommends, then you may need to install an optional plugin, such as poetry-plugin-export
, later at some point. In that case, use the pipx inject
command:
$ pipx inject poetry poetry-plugin-export poetry-plugin-bundle
injected package poetry-plugin-export into venv poetry
done! ✨ 🌟 ✨
injected package poetry-plugin-bundle into venv poetry
done! ✨ 🌟 ✨
The inject
subcommand expects the original package name that you installed before, like poetry
, followed by a list of one or more extra dependencies. This package name identifies the corresponding virtual environment that pipx
manages for you.
Note: You can optionally include version specifiers for these dependencies and use the --pip-args
parameter to pass additional arguments to the underlying pip
command. It can be especially useful if you’re behind a corporate proxy server and must pass its address to pip
.
To confirm these new dependencies have been added to the correct virtual environment, you can take advantage of the pipx runpip
command. It lets you run arbitrary pip
commands inside the app’s virtual environment:
In this case, you run pip list
inside Poetry’s virtual environment to get the complete list of the installed dependencies. You then filter the output of that command so that it only displays packages whose names contain the phrase “poetry.”
You can also use runpip
to upgrade or downgrade dependencies of a virtual environment managed by pipx
, as well as pin their versions by freezing them into a requirements file:
$ pipx runpip poetry install poetry-plugin-export==1.3.1
$ pipx runpip poetry install poetry-plugin-export --upgrade
$ pipx runpip poetry freeze > requirements.txt
While you could technically use runpip
to uninstall dependencies from a managed virtual environment, you’re better off with a more concise uninject
subcommand that pipx
has to offer:
$ pipx uninject poetry poetry-plugin-export
Uninjected package poetry-plugin-export
⮑ and its dependencies from venv poetry ✨ 🌟 ✨
When you uninstall an individual dependency by hand with pip
, you may leave transitive or indirect dependencies hanging around. In contrast, pipx uninject
takes care of them automatically, making sure no unused dependencies are left behind.
Another reason for calling pipx inject
might be when you want to run the mypyc
command from a virtual environment based on Python 3.12 or later. Mypy’s C extension module compiler requires setuptools, which was dropped from Python in the 3.12 release. At the time of writing, mypy didn’t list the setuptools
package as one of its dependencies, assuming it would still ship with Python. So, running mypyc
in the terminal would fail with an error:
$ mypyc
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'setuptools'
The pipx inject
command comes to the rescue, letting you install the missing dependency into the correct virtual environment:
$ pipx inject mypy setuptools
injected package setuptools into venv mypy
done! ✨ 🌟 ✨
With setuptools
now present, you can run mypyc
to compile a C extension module based on type-annotated Python code:
When you import the resulting dynamic-link library into a Python REPL session and call add()
, the function appears to be compiled into your platform’s native code:
As an alternative, instead of injecting the missing dependencies into a managed virtual environment, you could downgrade the underlying Python version to one that comes with setuptools. This is what you’ll do next.
Use a Specific Python Version in New Environments
By default, pipx
creates new virtual environments using the standard-library venv
module from the Python interpreter that you installed pipx
with. Specifically, if you typed python -m pip install pipx
, then it’ll use the interpreter of the activated environment. Conversely, if you used your operating system’s package manager, then it may use your global Python or a separate interpreter, which could be outdated.
You can override the default Python interpreter in two cases:
- Before installing a given Python package with
pipx
- As an afterthought, once you’ve already installed one
Case number one is more straightforward, so you’ll consider it first. For instructions on changing the Python version in existing virtual environments, head over to the next section, where you’ll use the reinstall
subcommand.
Both the pipx run
and pipx install
commands respect the PIPX_DEFAULT_PYTHON
environment variable, with which you can override the default Python interpreter:
Here, you use that environment variable to specify the path to a custom build of Python’s alpha release, which you cloned from GitHub and built from source. Then, using pipx
, you run an IPython session in a temporary virtual environment based on this alpha release. The message that IPython prints at startup confirms that you’re indeed running Python 3.13.0a4.
Note: There’s no need to compile Python from source to work through this example. You can install a pre-release version of Python with pyenv or leverage any existing Python installation that you already have on your system.
In addition to this, the pipx run
and pipx install
commands provide an optional --python
parameter, which lets you explicitly set the Python interpreter for the given virtual environment. It accepts one of the following values:
- File Path: The absolute path to a
python
executable in your file system - Executable: The executable name if it’s available on your
PATH
variable - Version: The Python version recognized by the Python Launcher on Windows
Assuming you have pyenv or pyenv-win configured, you can install an older Python release alongside your system-wide interpreter and other interpreters that you might have installed or compiled from source code. Next, you should locate the corresponding python
executable by navigating to the directory where pyenv stores its Python versions. Or, you can temporarily set the newly installed Python in your shell and check the path to its executable:
Once you know the full path to the preferred Python interpreter, you can pass it to pipx
when installing mypy
or other package:
The output of the command confirms that pipx
created a virtual environment based on the given Python interpreter. You may list the installed packages again with pipx list
to double check.
Surprisingly, you’ll get the same error as before when you try running mypyc
, even though you’re now using an older Python version that should generally install setuptools in new environments:
As you can see, setuptools is nowhere to be found in the managed virtual environment. It turns out that pipx
creates minimal environments that contain just the installed package and its dependencies. It’s because pipx
runs the venv
module with the --without-pip
switch, which skips installing packages like pip
and setuptools
. So, you’ll need to install setuptools by hand anyway.
What about existing apps that you installed with pipx
? You’re about to discover how you can control the Python versions in their respective virtual environments.
Change the Python Version in Existing Environments
If you only want to change the underlying Python version for an installed app while keeping everything else untouched, then you can leverage the pipx reinstall
command. When executed without any extra parameters, it’ll remove the package along with its isolated virtual environment and install it again using the same options you specified originally.
Note: If you invoke pipx reinstall
in a new terminal session, it won’t see the PIPX_DEFAULT_PYTHON
environment variable unless you define it permanently in your shell configuration. This means pipx
will fall back to its default Python interpreter, which may be different than the previous version you used for that same environment.
That said, the pipx reinstall
command also accepts the --python
parameter, so you can recreate the virtual environment of an installed app using any Python version that you like:
You can now start ipython
from anywhere in your terminal, and it’ll run on top of the Python 3.13 alpha 4 release that you specified with pipx
.
Note: Executing pipx install
with the --python
option and the --force
flag won’t work because the former gets ignored when you use both parameters together.
It can be particularly useful to reinstall a Python app with pipx
when you’ve upgraded your primary Python interpreter and would like to switch to a newer version with the --python
option. Because upgrading the Python release in virtual environments is so common, pipx
provides another convenient subcommand, reinstall-all
, which does the upgrade or downgrade in all virtual environments at once:
Note that this will reinstall all packages, even if some of them already use the desired Python version. To prevent this, or to keep some of your apps intact, you can optionally exclude certain packages by listing them through the --skip
argument:
Make sure that the corresponding Python executable can be found in one of the folders specified in your PATH
variable before proceeding. When this command finishes executing, pipx
will have reinstalled all but the explicitly excluded Python apps using the specified version of Python.
That concludes this tutorial. If you’re thirsty for more, then you can explore a comprehensive collection of command examples in the official documentation. Note that pipx
is under active development, which means that some of these examples may no longer work the way they’re advertised. In such cases, it’s best to study the tool’s source code, which is available on GitHub.
Next Steps: Make Your Own App for pipx
Now that you understand the nuts and bolts of pipx
, you might feel empowered to build your own Python package with runnable entry points and share it with the world. For example, you could create a command-line game like the Game of Life, Hangman, Tic-Tac-Toe, or a Wordle clone. Or, maybe you’re into data science and have ideas for more serious projects.
Either way, once you’re past the prototyping phase, pick a Python packaging tool like setuptools, Flit, or Poetry, and specify your entry points accordingly. Then, build a wheel distribution package and publish it on PyPI. As a rule of thumb, you should first upload your package to TestPyPI for verification.
When you’re ready to show off your work, don’t forget to mention it in the comments below!
Conclusion
At this point, you have a pretty good idea about the range of problems that pipx
helps solve in your daily Python programming. You know how to install and configure pipx
, as well as how to run it without installation. With this knowledge, you can safely run command-line Python applications in isolated virtual environments without risking dependency conflicts.
In this tutorial, you’ve learned how to:
- Turn the Python Package Index (PyPI) into an app marketplace
- Run installed applications without explicitly calling Python
- Avoid dependency conflicts between different applications
- Try throw-away applications in temporary locations
- Manage the installed applications and their environments
Incorporating pipx
into your programmer’s tool kit will surely increase your productivity when working with Python.
Get Your Cheatsheet: Click here to download the free cheatsheet of pipx commands you can use to install and execute Python applications.
Take the Quiz: Test your knowledge with our interactive “Install and Execute Python Applications Using pipx” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Install and Execute Python Applications Using pipxIn this quiz, you'll test your understanding of how Python apps are run from isolated virtual environments using the pipx tool. With this knowledge, you'll be able to safely run Python apps that are installed globally in your operating system.