I have been told that
pipx is a very good tool to install and run Python
applications in isolated environments. That description almost immediately
reminds me of another tool -
pyenv. Even though they address different
needs, I find myself mixing them up. The purpose of this post is to describe
what the tools try to accomplish and how they go about doing so. A pre-requisite
to this discussion is an introduction to how the system
variable is used.
At a fundamental level,
$PATH is an environment variable which consists of
a list of directories separated by colons (
:). Here is a quick example,
When a command is entered, the OS scans this group of directories (in the order
given) for a corresponding executable to run. For example, assume we wish to
docker-compose executable. Here are the different attempts the OS
If it is unable to find the executable within any of the directories on the
$PATH , an error message is returned to the user.
A … divergence, or an exception to the above behaviour is when
involved. You can think of them as light-weight utilities which process the
name of the executable searched for within the directory and respond
pyenv is a tool to help manage different Python environments on the same
system. For example, one might have Python 2.7 installed for one project and
Python 3.8 installed for another. On this system, if we were to randomly run
$ python --help which version would we reasonably expect to answer?
One approach is to manually manage everything, adding or removing entries from
$PATH as needed. This gets messy and troublesome. A better alternative is
to use the
pyenv tool. When installed and initialized,
pyenv adds a
shim to the
$PATH environment variable. The end result looks
something like this,
At the point, every command executed is processed via
pyenv (via the shim).
If it decides that it is a Python-related command,
pyenv will redirect
execution to the corrsponding Python executable.
For the most part, this works very well. An interesting side-effect of this
design, is that the
pyenv tool needs to be active on the system. In
pipx does not.
As per the official documentation “pipx is a tool to help you install and run end-user applications written in Python”. It will be helpful to understand what we mean by “end-user applications” in this context. The background is that Python and PyPI allow developers to distribute code with “console script entry points”. These allow users to call into the Python code from the command line, effectively acting as standalong applications.
pipx is a tool to install and run any of these standalone applications in a safe, convenient and reliable way.
On hearing all that, I expected to install
pipx as a global tool on my
system, similar to what I did for
pyenv. It greatly confused me that this
was not the case. In fact if you want to keep environments isolated, the
easiest way to use pipx is to create a new Python virtual envrionment and just
install it via
pip ! Something like this,
At this point, let us assume that we want to install the
pycowsay CLI tool
from PyPI. Since
pipx is already present in our current virtualenv, all we
need to do is,
Running the above command will create a new virtualenv at
/home/USER/.local/pipx/venvs and a symbolic link in the
/home/USER/.local/bin directory which points to the executable within the
What is most remarkable is that we can now delete the virtualenv created for
pipx, but our installation of
pycowsay will still be present!
Oookay. That was disappointing. Looks like my original intuition about
being dependant on the virtualenv from where it gets installed from is accurate.
In this scenario, what I would like to happen is for
pycowsay to pick up my
“root” Python 3.8.5 executable. Hmm… according to the
pipx docs, that
might be possible. Lets give this a shot,
Yay! That worked!!
In conclusion, this is going to my general approach to installing things via
Author Abraham Varricatt
LastMod 2021 March 21
Markdown The Markdown version »