Install and Execute Python Applications Using pipx

Install and Execute Python Applications Using pipx

by Bartosz Zaczyński Apr 03, 2024 intermediate tools

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.

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.

Take the Quiz: Test your knowledge with our interactive “Install and Execute Python Applications Using pipx” quiz. Upon completion you will receive a score so you can track your learning progress over time:


Interactive Quiz

Install and Execute Python Applications Using pipx

In 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:

  1. 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.
  2. Runnable: These are usually command-line utility tools like black, isort, or flake8 that assist you during the development phase. They could also be full-fledged applications like bpython or the JupyterLab environment, which is primarily implemented in a foreign TypeScript programming language.
  3. 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.

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.

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.

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:

Windows PowerShell
PS> python .\pipx.pyz --version
1.4.3
Shell
$ python pipx.pyz --version
1.4.3

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:

Shell
$ 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:

Windows PowerShell
PS> python .\pipx.pyz install ipython
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython.exe
    - ipython3.exe
  These manual pages are now globally available
    - man1\ipython.1
done! ✨ 🌟 ✨
Shell
$ python pipx.pyz install ipython
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython
    - ipython3
  These manual pages are now globally available
    - man1/ipython.1
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> python -m pip install pipx
Shell
$ python -m pip install pipx

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:

Windows PowerShell
PS> scoop install pipx

Unfortunately, there’s no corresponding pipx package for Chocolatey, which you might’ve used to install Python if you followed Real Python’s Windows coding setup guide mentioned in the introduction.

Shell
$ sudo apt install pipx
Shell
$ brew install pipx

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:

Windows PowerShell
PS> pipx install ipython
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython.exe
    - ipython3.exe
  These manual pages are now globally available
    - man1\ipython.1
⚠️  Note: 'C:\Users\User\.local\bin' is not on your PATH environment variable.
 ⮑  These apps will not be globally accessible until your PATH is updated.
 ⮑  Run `pipx ensurepath` to automatically add it, or manually modify your
 ⮑  PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨
Shell
$ pipx install ipython
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython
    - ipython3
  These manual pages are now globally available
    - man1/ipython.1
⚠️  Note: '/home/user/.local/bin' is not on your PATH environment variable.
 ⮑  These apps will not be globally accessible until your PATH is updated.
 ⮑  Run `pipx ensurepath` to automatically add it, or manually modify your
 ⮑  PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨
Shell
$ pipx install ipython
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython
    - ipython3
  These manual pages are now globally available
    - man1/ipython.1
⚠️  Note: '/Users/User/.local/bin' is not on your PATH environment variable.
 ⮑  These apps will not be globally accessible until your PATH is updated.
 ⮑  Run `pipx ensurepath` to automatically add it, or manually modify your
 ⮑  PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> pipx ensurepath
Success! Added C:\Users\User\.local\bin to the PATH environment variable.

Consider adding shell completions for pipx.
⮑ Run 'pipx completions' for instructions.

You will need to open a new terminal or re-login for the PATH changes
⮑ to take effect.

Otherwise pipx is ready to go! ✨ 🌟 ✨
Shell
$ pipx ensurepath
Success! Added /home/user/.local/bin to the PATH environment variable.

Consider adding shell completions for pipx.
⮑ Run 'pipx completions' for instructions.

You will need to open a new terminal or re-login for the PATH changes
⮑ to take effect.

Otherwise pipx is ready to go! ✨ 🌟 ✨
Shell
$ pipx ensurepath
Success! Added /Users/User/.local/bin to the PATH environment variable.

Consider adding shell completions for pipx.
⮑ Run 'pipx completions' for instructions.

You will need to open a new terminal or re-login for the PATH changes
⮑ to take effect.

Otherwise pipx is ready to go! ✨ 🌟 ✨

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:

Shell ~/.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:

Windows PowerShell
PS> pipx environment
Environment variables (set by user):

PIPX_HOME=
PIPX_BIN_DIR=
PIPX_MAN_DIR=
PIPX_SHARED_LIBS=
PIPX_DEFAULT_PYTHON=
USE_EMOJI=

Derived values (computed by pipx):

PIPX_HOME=C:\Users\User\AppData\Local\pipx\pipx
PIPX_BIN_DIR=C:\Users\User\.local\bin
PIPX_MAN_DIR=C:\Users\User\.local\share\man
PIPX_SHARED_LIBS=C:\Users\User\AppData\Local\pipx\pipx\shared
PIPX_LOCAL_VENVS=C:\Users\User\AppData\Local\pipx\pipx\venvs
PIPX_LOG_DIR=C:\Users\User\AppData\Local\pipx\pipx\Logs
PIPX_TRASH_DIR=C:\Users\User\AppData\Local\pipx\pipx\trash
PIPX_VENV_CACHEDIR=C:\Users\User\AppData\Local\pipx\pipx\Cache
PIPX_DEFAULT_PYTHON=C:\Users\User\.pyenv\pyenv-win\versions\3.12.2\python.exe
USE_EMOJI=true
Shell
$ pipx environment
Environment variables (set by user):

PIPX_HOME=
PIPX_BIN_DIR=
PIPX_MAN_DIR=
PIPX_SHARED_LIBS=
PIPX_DEFAULT_PYTHON=
USE_EMOJI=

Derived values (computed by pipx):

PIPX_HOME=/home/user/.local/pipx
PIPX_BIN_DIR=/home/user/.local/bin
PIPX_MAN_DIR=/home/user/.local/share/man
PIPX_SHARED_LIBS=/home/user/.local/pipx/shared
PIPX_LOCAL_VENVS=/home/user/.local/pipx/venvs
PIPX_LOG_DIR=/home/user/.local/pipx/logs
PIPX_TRASH_DIR=/home/user/.local/pipx/.trash
PIPX_VENV_CACHEDIR=/home/user/.local/pipx/.cache
PIPX_DEFAULT_PYTHON=/home/user/.pyenv/versions/3.12.2/bin/python
USE_EMOJI=true
Shell
$ pipx environment
Environment variables (set by user):

PIPX_HOME=
PIPX_BIN_DIR=
PIPX_MAN_DIR=
PIPX_SHARED_LIBS=
PIPX_DEFAULT_PYTHON=
USE_EMOJI=

Derived values (computed by pipx):

PIPX_HOME=/Users/User/.local/pipx
PIPX_BIN_DIR=/Users/User/.local/bin
PIPX_MAN_DIR=/Users/User/.local/share/man
PIPX_SHARED_LIBS=/Users/User/.local/pipx/shared
PIPX_LOCAL_VENVS=/Users/User/.local/pipx/venvs
PIPX_LOG_DIR=/Users/User/.local/pipx/logs
PIPX_TRASH_DIR=/Users/User/.local/pipx/.trash
PIPX_VENV_CACHEDIR=/Users/User/.local/pipx/.cache
PIPX_DEFAULT_PYTHON=/Users/User/.pyenv/versions/3.12.2/bin/python
USE_EMOJI=true

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:

Shell
$ 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:

Shell
$ 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.

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:

Shell
$ 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.

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:

Shell
$ 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:

Shell
$ 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.

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:

Shell
$ 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:

Shell
$ 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:

Python 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:

Windows PowerShell
PS> pipx install ruff
  installed package ruff 0.2.2, installed using Python 3.12.2
  These apps are now globally available
    - ruff.exe
done! ✨ 🌟 ✨
Shell
$ pipx install ruff
  installed package ruff 0.2.2, installed using Python 3.12.2
  These apps are now globally available
    - ruff
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> ruff --version
ruff 0.2.2

PS> Get-Command ruff

CommandType     Name         Version     Source
-----------     ----         -------     ------
Application     ruff.exe     0.0.0.0     c:\users\user\.local\bin\ruff.exe
Shell
$ ruff --version
ruff 0.2.2

$ which ruff
/home/user/.local/bin/ruff
Shell
$ ruff --version
ruff 0.2.2

$ which ruff
/Users/User/.local/bin/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.

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:

Windows PowerShell
PS> pipx install mypy
  installed package mypy 1.8.0, installed using Python 3.12.2
  These apps are now globally available
    - dmypy.exe
    - mypy.exe
    - mypyc.exe
    - stubgen.exe
    - stubtest.exe
done! ✨ 🌟 ✨
Shell
$ pipx install mypy
  installed package mypy 1.8.0, installed using Python 3.12.2
  These apps are now globally available
    - dmypy
    - mypy
    - mypyc
    - stubgen
    - stubtest
done! ✨ 🌟 ✨

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:

Shell
$ 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:

Windows PowerShell
PS> pipx install pandas
Note: Dependent package 'numpy' contains 1 apps
  - f2py.exe

No apps associated with package pandas. Try again with '--include-deps'
⮑ to include apps of dependent packages, which are listed above.
⮑ If you are attempting to install a library, pipx should
⮑ not be used. Consider using pip or a similar tool instead.
Shell
$ pipx install pandas
Note: Dependent package 'numpy' contains 1 apps
  - f2py

No apps associated with package pandas. Try again with '--include-deps'
⮑ to include apps of dependent packages, which are listed above.
⮑ If you are attempting to install a library, pipx should
⮑ not be used. Consider using pip or a similar tool instead.

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:

Windows PowerShell
PS> pipx install --include-deps pandas
  installed package pandas 2.2.1, installed using Python 3.12.2
  These apps are now globally available
    - f2py.exe
done! ✨ 🌟 ✨
Shell
$ pipx install --include-deps pandas
  installed package pandas 2.2.1, installed using Python 3.12.2
  These apps are now globally available
    - f2py
done! ✨ 🌟 ✨

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:

Shell
$ 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:

Windows PowerShell
PS> pipx run poetry --version
⚠️  poetry is already on your PATH and installed
⮑ at c:\Users\User\.local\bin\poetry.EXE.
⮑ Downloading and running anyway.
Poetry (version 1.8.0)

PS> pipx install poetry
⚠️  Note: poetry was already on your PATH at c:\Users\User\poetry
  installed package poetry 1.8.0, installed using Python 3.12.2
  These apps are now globally available
    - poetry.exe
done! ✨ 🌟 ✨
Shell
$ pipx run poetry --version
⚠️  poetry is already on your PATH and installed
⮑ at /home/user/.local/bin/poetry.
⮑ Downloading and running anyway.
Poetry (version 1.8.0)

$ pipx install poetry
⚠️  Note: poetry was already on your PATH at /home/user/poetry
  installed package poetry 1.8.0, installed using Python 3.12.2
  These apps are now globally available
    - poetry
done! ✨ 🌟 ✨
Shell
$ pipx run poetry --version
⚠️  poetry is already on your PATH and installed
⮑ at /Users/User/.local/bin/poetry.
⮑ Downloading and running anyway.
Poetry (version 1.8.0)

$ pipx install poetry
⚠️  Note: poetry was already on your PATH at /Users/User/poetry
  installed package poetry 1.8.0, installed using Python 3.12.2
  These apps are now globally available
    - poetry
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> pipx list
venvs are in C:\Users\User\AppData\Local\pipx\pipx\venvs
apps are exposed on your $PATH at C:\Users\User\.local\bin
manual pages are exposed at C:\Users\User\.local\share\man
   package ipython 8.22.1, installed using Python 3.12.2
    - ipython.exe
    - ipython3.exe
    - man1\ipython.1
   package mypy 1.8.0, installed using Python 3.12.2
    - dmypy.exe
    - mypy.exe
    - mypyc.exe
    - stubgen.exe
    - stubtest.exe
   package pandas 2.2.1, installed using Python 3.12.2
    - f2py.exe
   package poetry 1.8.0, installed using Python 3.12.2
    - poetry.exe
   package ruff 0.2.2, installed using Python 3.12.2
    - ruff.exe
Shell
$ pipx list
venvs are in /home/user/.local/share/pipx/venvs
apps are exposed on your $PATH at /home/user/.local/bin
manual pages are exposed at /home/user/.local/share/man
   package ipython 8.22.1, installed using Python 3.12.2
    - ipython
    - ipython3
    - man1/ipython.1
   package mypy 1.8.0, installed using Python 3.12.2
    - dmypy
    - mypy
    - mypyc
    - stubgen
    - stubtest
   package pandas 2.2.1, installed using Python 3.12.2
    - f2py
   package poetry 1.8.0, installed using Python 3.12.2
    - poetry
   package ruff 0.2.2, installed using Python 3.12.2
    - ruff
Shell
$ pipx list
venvs are in /User/User/.local/share/pipx/venvs
apps are exposed on your $PATH at /User/User/.local/bin
manual pages are exposed at /User/User/.local/share/man
   package ipython 8.22.1, installed using Python 3.12.2
    - ipython
    - ipython3
    - man1/ipython.1
   package mypy 1.8.0, installed using Python 3.12.2
    - dmypy
    - mypy
    - mypyc
    - stubgen
    - stubtest
   package pandas 2.2.1, installed using Python 3.12.2
    - f2py
   package poetry 1.8.0, installed using Python 3.12.2
    - poetry
   package ruff 0.2.2, installed using Python 3.12.2
    - ruff

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.

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:

Shell
$ 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:

Shell
$ 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:

Shell
$ 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:

Shell
$ 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:

Windows PowerShell
PS> pipx install ruff==0.0.292
'ruff' already seems to be installed. Not modifying existing installation
⮑ in 'C:\Users\User\AppData\Local\pipx\pipx\venvs\ruff'.
⮑ Pass '--force' to force installation.
Shell
$ pipx install ruff==0.0.292
'ruff' already seems to be installed. Not modifying existing installation
⮑ in '/home/user/.local/share/pipx/venvs/ruff'.
⮑ Pass '--force' to force installation.
Shell
$ pipx install ruff==0.0.292
'ruff' already seems to be installed. Not modifying existing installation
⮑ in '/Users/User/.local/share/pipx/venvs/ruff'.
⮑ Pass '--force' to force installation.

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:

Windows PowerShell
PS> pipx install --force ruff==0.0.292
Installing to existing venv 'ruff'
  installed package ruff 0.0.292, installed using Python 3.12.2
  These apps are now globally available
    - ruff.exe
done! ✨ 🌟 ✨
Shell
$ pipx install --force ruff==0.0.292
Installing to existing venv 'ruff'
  installed package ruff 0.0.292, installed using Python 3.12.2
  These apps are now globally available
    - ruff
done! ✨ 🌟 ✨

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.

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:

Shell
$ 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:

Shell
$ 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:

Shell
$ 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.

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:

Windows PowerShell
PS> pipx runpip poetry list | Select-String 'poetry'

poetry               1.8.0
poetry-core          1.9.0
poetry-plugin-bundle 1.3.0
poetry-plugin-export 1.6.0
Shell
$ pipx runpip poetry list | grep poetry
poetry               1.8.0
poetry-core          1.9.0
poetry-plugin-bundle 1.3.0
poetry-plugin-export 1.6.0

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:

Shell
$ 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:

Shell
$ 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:

Shell
$ 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:

Shell
$ 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:

Windows PowerShell
PS> Get-Content .\adder.py
def add(x: float, y: float) -> float:
    return x + y

PS> mypyc .\adder.py
running build_ext
building 'adder' extension
creating build\temp.win-amd64-cpython-312
creating build\temp.win-amd64-cpython-312\Release
creating build\temp.win-amd64-cpython-312\Release\build
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\...
...
creating C:\Users\User\build\lib.win-amd64-cpython-312
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\...
   Creating library build\...\Release\build\adder.cp312-win_amd64.lib and ...
Generating code
Finished generating code
copying build\lib.win-amd64-cpython-312\adder.cp312-win_amd64.pyd ->
Shell
$ cat adder.py
def add(x: float, y: float) -> float:
    return x + y

$ mypyc adder.py
running build_ext
building 'adder' extension
creating build/temp.linux-x86_64-cpython-312
creating build/temp.linux-x86_64-cpython-312/build
gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC ...
creating build/lib.linux-x86_64-cpython-312
gcc -shared -L/home/user/.pyenv/versions/3.12.2/lib -Wl,-rpath,/home/...
copying build/.../adder.cpython-312-x86_64-linux-gnu.so ->
Shell
$ cat adder.py
def add(x: float, y: float) -> float:
    return x + y

$ mypyc adder.py
running build_ext
building 'adder' extension
creating build/temp.macosx-10.15-x86_64-cpython-312
creating build/temp.macosx-10.15-x86_64-cpython-312/build
clang -fno-strict-overflow -Wsign-compare -Wunreachable-code -fno-common ...
creating build/lib.macosx-10.15-x86_64-cpython-312
clang -bundle -undefined dynamic_lookup -isysroot /Library/Developer/Command...
copying build/lib.macosx-10.15-x86_64-cpython-312/adder.cpython-312-darwin.so -

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:

Python
>>> import adder

>>> adder
<module 'adder' from 'C:\\Users\\User\\adder.cp312-win_amd64.pyd'>

>>> adder.add
<built-in function add>

>>> adder.add(3.14, 2.72)
5.86
Python
>>> import adder

>>> adder
<module 'adder' from '/home/user/adder.cpython-312-x86_64-linux-gnu.so'>

>>> adder.add
<built-in function add>

>>> adder.add(3.14, 2.72)
5.86
Python
>>> import adder

>>> adder
<module 'adder' from '/Users/User/adder.cpython-312-darwin.so'>

>>> adder.add
<built-in function add>

>>> adder.add(3.14, 2.72)
5.86

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:

  1. Before installing a given Python package with pipx
  2. 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:

Windows PowerShell
PS> $env:PIPX_DEFAULT_PYTHON="C:\path\to\python-3.13.0a4\bin\python3.exe"
PS> pipx run ipython
Python 3.13.0a4 (tags/v3.13.0a4:9d34f60783, Feb 26 2024, 13:03:08) [MSC v.1937 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.22.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]:
Shell
$ export PIPX_DEFAULT_PYTHON=/path/to/python-3.13.0a4/bin/python3
$ pipx run ipython
Python 3.13.0a4 (tags/v3.13.0a4:9d34f60783, Feb 26 2024, 13:03:08) [GCC 13.2.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.22.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]:
Shell
$ export PIPX_DEFAULT_PYTHON=/path/to/python-3.13.0a4/bin/python3
$ pipx run ipython
Python 3.13.0a4 (tags/v3.13.0a4:9d34f60783, Feb 26 2024, 13:03:08) [Clang 12.0.0 (clang-1200.0.32.29)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.22.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

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.

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:

Windows PowerShell
PS> pyenv install 3.11.8
:: [Info] ::  Mirror: https://www.python.org/ftp/python
:: [Downloading] ::  3.11.8 ...
:: [Downloading] ::  From https://www.python.org/ftp/python/3.11.8/python-3.11.8-amd64.exe
:: [Downloading] ::  To   C:\Users\User\.pyenv\pyenv-win\install_cache\python-3.11.8-amd64.exe
:: [Installing] ::  3.11.8 ...
:: [Info] :: completed! 3.11.8
PS> pyenv shell 3.11.8
PS> pyenv which python
C:\Users\User\.pyenv\pyenv-win\versions\3.11.8\python.exe
Shell
$ pyenv install 3.11.8
Downloading Python-3.11.8.tar.xz...
-> https://www.python.org/ftp/python/3.11.8/Python-3.11.8.tar.xz
Installing Python-3.11.8...
Installed Python-3.11.8 to /home/user/.pyenv/versions/3.11.8
$ pyenv shell 3.11.8
$ pyenv which python
/home/user/.pyenv/versions/3.11.8/bin/python
Shell
$ pyenv install 3.11.8
python-build: use openssl@3 from homebrew
python-build: use readline from homebrew
Downloading Python-3.11.8.tar.xz...
-> https://www.python.org/ftp/python/3.11.8/Python-3.11.8.tar.xz
Installing Python-3.11.8...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.11.8 to /Users/User/.pyenv/versions/3.11.8
$ pyenv shell 3.11.8
$ pyenv which python
/Users/User/.pyenv/versions/3.11.8/bin/python

Once you know the full path to the preferred Python interpreter, you can pass it to pipx when installing mypy or other package:

Windows PowerShell
PS> pipx install --python=C:\Users\User\.pyenv\...\3.11.8\python.exe mypy
  installed package mypy 1.8.0, installed using Python 3.11.8
  These apps are now globally available
    - dmypy.exe
    - mypy.exe
    - mypyc.exe
    - stubgen.exe
    - stubtest.exe
done! ✨ 🌟 ✨
Shell
$ pipx install --python=/home/user/.pyenv/versions/3.11.8/bin/python mypy
  installed package mypy 1.8.0, installed using Python 3.11.8
  These apps are now globally available
    - dmypy
    - mypy
    - mypyc
    - stubgen
    - stubtest
done! ✨ 🌟 ✨
Shell
$ pipx install --python=/Users/User/.pyenv/versions/3.11.8/bin/python mypy
  installed package mypy 1.8.0, installed using Python 3.11.8
  These apps are now globally available
    - dmypy
    - mypy
    - mypyc
    - stubgen
    - stubtest
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> pipx runpip mypy list
Package           Version
----------------- -------
mypy              1.8.0
mypy-extensions   1.0.0
pip               24.0
typing_extensions 4.9.0
Shell
$ pipx runpip mypy list
Package           Version
----------------- -------
mypy              1.8.0
mypy-extensions   1.0.0
pip               24.0
typing_extensions 4.9.0

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.

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:

Windows PowerShell
PS> pipx reinstall --python=C:\path\to\python-3.13.0a4\bin\python3.exe ipython
uninstalled ipython! ✨ 🌟 ✨
  installed package ipython 8.22.1, installed using Python 3.13.0a4
  These apps are now globally available
    - ipython.exe
    - ipython3.exe
  These manual pages are now globally available
    - man1\ipython.1
done! ✨ 🌟 ✨
Shell
$ pipx reinstall --python=/path/to/python-3.13.0a4/bin/python3 ipython
uninstalled ipython! ✨ 🌟 ✨
  installed package ipython 8.22.1, installed using Python 3.13.0a4
  These apps are now globally available
    - ipython
    - ipython3
  These manual pages are now globally available
    - man1/ipython.1
done! ✨ 🌟 ✨

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.

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:

Windows PowerShell
PS> pipx reinstall-all --python=python3.12.exe
uninstalled ipython! ✨ 🌟 ✨
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython.exe
    - ipython3.exe
  These manual pages are now globally available
    - man1/ipython.1
done! ✨ 🌟 ✨
uninstalled pandas! ✨ 🌟 ✨
  installed package pandas 2.2.1, installed using Python 3.12.2
  These apps are now globally available
    - f2py.exe
done! ✨ 🌟 ✨

Shell
$ pipx reinstall-all --python=python3.12
uninstalled ipython! ✨ 🌟 ✨
  installed package ipython 8.22.1, installed using Python 3.12.2
  These apps are now globally available
    - ipython
    - ipython3
  These manual pages are now globally available
    - man1/ipython.1
done! ✨ 🌟 ✨
uninstalled pandas! ✨ 🌟 ✨
  installed package pandas 2.2.1, installed using Python 3.12.2
  These apps are now globally available
    - f2py
done! ✨ 🌟 ✨

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:

Windows PowerShell
PS> pipx reinstall-all --python=python3.12.exe --skip poetry pandas mypy
Shell
$ pipx reinstall-all --python=python3.12 --skip poetry pandas mypy

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.

Take the Quiz: Test your knowledge with our interactive “Install and Execute Python Applications Using pipx” quiz. Upon completion you will receive a score so you can track your learning progress over time:


Interactive Quiz

Install and Execute Python Applications Using pipx

In 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.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Bartosz Zaczyński

Bartosz Zaczyński Bartosz Zaczyński

Bartosz is a bootcamp instructor, author, and polyglot programmer in love with Python. He helps his students get into software engineering by sharing over a decade of commercial experience in the IT industry.

» More about Bartosz

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Tutorial Categories: intermediate tools