Pipx: A python package consumption tool for CLI packages
Tags: python, cli, package, pipx
Published: 2022-03-20 15:51:42

## Introduction

Previously, I explored the [pipenv](https://mr-destructive.github.io/techstructive-blog/pipenv-intro/) as a python package management tool and this week it is time for exploring a python CLI package isolation tool called `pipx`. It is a really simple and powerful tool for running commands as an executable from an isolated environment. Those commands should be associated with a python package that has CLI. In pipx, we install the package once and we can use the package anywhere on our system isolated from other virtual environments. 

In this article, We will explore the pipx package/tool in python. From installation to setting up your environment and removing some friction in your python workflow. This won't be an in-depth guide of pipx, though we would cover a few python packages that can be easily used in your environment.

## What is Pipx

Pipx is a python package that works similar to `pip` but it is quite specific to the usage. It can run CLI commands of any python package from anywhere on your system. It uses its own virtual environment for managing the packages and the python version. 

**NOTE**

- Pipx is a tool to install and execute CLI commands provided in the python packages
- Pipx is not a python package management tool like pip or pipenv.

Pipx is similar to `npx` for nodejs. Though the major difference is that pipx runs and installs all packages/tools globally unlike npx. 


## Install Pipx

**Pipx requires Python 3.6 or above.**

- You can install it normally like a python package with pip:

```
pip install pipx
```

To find out if pipx was successfully installed, you can simply type in the command:

```
pipx --version
```

If it gives a number and no errors, it has been successfully installed in your system globally.

## Pipx Commands 

The primary commands that pipx can use are:

1. pipx install
2. pipx list
3. pipx run
4. pipx inject
5. pipx uninstall

For further command options for a specific use case, you can use the `pipx -h` command to get the detailed list of commands and options available in pipx.

Also, the documentation of pipx is really incredibly beginner-friendly. You can follow up with the article from the [documentation](https://pypa.github.io/pipx/) webpage or the [GitHub](https://github.com/pypa/pipx/) repository. The documentation and the webpage are simple single-page websites that really make learning the tool easier and it also has a well-documented package.

### Pipx Install Command

Pipx can install packages in a virtual environment specific to the package provided. This means that you will have different virtual envs for each package you install and not a single virtual env for a project, it creates and makes the package venvs accessible globally. The next step after installing the package in a different venv is to make that package commands accessible via the PATH environment variable. 

```
pipx install <package_name>
```

If say we install [pgcli](https://pypi.org/project/pgcli/), a package for interacting with postgres database using python in the Command line. We will simply enter the following commands:

```
pipx install pgcli
```

![install package with pipx](https://res.cloudinary.com/techstructive-blog/image/upload/v1647783261/blog-media/du830o3fbqogvkaesxnq.png)

We can use the package pgcli globally in our system. So, we have access to the databases in the local Postgres server. We can run the commands as normally as we want using the pgcli by just prefixing with `pipx run`.

```
pipx run pgcli <local_database_name> -U postgres
```

![PGCLI demonstration GIF](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782221/blog-media/dfpwlxkh5ybqj5pdos8d.gif)

This is a really cool way to interact with CLI applications without installing separately or globally, using pipx the virtual environment for the specific package makes it a clean and persistent behavior for running the commands anywhere in the system.

If you want to know more about pgcli tool/package in Python, you can it's [documentation](https://www.pgcli.com/docs) webpage or the [GitHub](https://github.com/dbcli/pgcli) repository.

#### Pipx Default PATH

The default path at which pipx stores the virtual environments for each package is by default the `~/.local/pipx/venvs`(here ~ refers to the root/default directory), the documentation says that it can be changed by editing the environment variable `PIPX_HOME`. 

The default path at which pipx stores the binaries/command apps for each package is stored in the path `~/.local/bin`, even this path can be modified by editing the environment variable `PIPX_BIN_DIR`

### Pipx List Command

Pipx list command simply lists the executables or the commands you can run with pipx. This command will display the commands associated with the packages that are installed in the pipx environment. 

```
pipx list
```

![Pipx list output](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782349/blog-media/qu95nynklbuceqqd9qke.png)

This command gives a detailed list of the commands associated with their respective packages. It also gives the meta-information like the Python version in which the package was installed. 


### Pipx Run Command

The most useful command in pipx has to be `pipx run`, this command can execute provide package along with the specified command associated with the package. 

The structure of the command is as follows:

```
pipx run <package_name> <command>
```
The pipx documentation refers to the `command` as an `APP`, as it is an executable created from the package specification.

If the APP/command name is not matching the `package_name`(most of the time it won't), you need to add an argument to the run command.

```
pipx run --spec <package_name> <command>
```

The `--spec` option allows specifying a certain package to be used while running the command/APP. Using this option with the `pipx run` command, we can run package-specific commands. For example, if we want to run an ipython from the terminal, without messing up the current environment i.e. without installing any package. You can do that by using pipx.

```
pipx install dailydotdev-bookmark-cli

pipx run --spec dailydotdev-bookmark-cli bookamrks
```

![dailydotdev-bookmark-cli demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782547/blog-media/vsfmwlzazqtosuwttexb.gif)

This is my shameless plug of installing my [first python package](https://github.com/Mr-Destructive/bookmarks-cli). The command used for the CLI is totally not related to the package name and hence we have to use the `--spec` option.

## Install and Run packages from Pipx

Any python package which provide a Command Line Interface can be installed and run with pipx. Some of the packages like [pytest](https://docs.pytest.org/en/7.1.x/contents.html), [pipenv](https://pipenv-fork.readthedocs.io/en/latest/install.html), [rich-cli](https://github.com/Textualize/rich-cli), [Black code formatter](https://github.com/psf/black), [markata](https://markata.dev/) and many others. 
You can install any of the packages which do have a cli to interact with on the go with pipx. 

### Running Ipython shell

We can use [Ipython](https://pypi.org/project/ipython/) shell from pipx as an isolated environment. We simply install the package first, after installing the package it creates the virtual environment. Creating a separate virtual environment registers the app/command binaries into the PATH environment of the system so that they can be accessed globally. 

```
pipx install ipython

pipx run ipython
```

![IPython pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782651/blog-media/ssgymybn0dwi8ocs6xpf.png)

For further documentation on ipython using the CLI, you can refer to the [GitHub](https://github.com/ipython/ipython) link or the [documentation](https://ipython.org/ipython-doc/3/interactive/reference.html#command-line-usage) page.

### Reading an IPYNB file from pipx with JUT

If you just want to read an ipynb file from the terminal, you can do that using [jut](https://pypi.org/project/jut/) by specifying the command:

```
pipx install jut

pipx run jut <notebook.ipynb>
```

![jut pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782686/blog-media/ddm5uiqarjjmedhqvcsk.png)

You can find more information on JUT via their official [GitHub](https://github.com/kracekumar/jut) repository.

### Using rich-cli to display text using pipx

We can even use [Rich-CLI](https://pypi.org/project/rich-cli/) to print rich content in the project. Rich-CLI as the name suggests is a CLI for the Rich package in python. It is really intuitive and simple to use. If we want to take snaps of the rich content of a markdown file, source file, dataset, etc. rich-cli is a tool that can quickly do that. Use pipx to install the package globally and simply run wherever required in an isolated environment.

```
pipx install rich-cli

pipx run --spec rich-cli rich "[blue]Hello[/], [yellow]World[/]!" --print
```

![rich-cli pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782738/blog-media/xvdyhxjpj2hsghl2x1ng.png)


This will give you a colorful display of "Hello, World" without you messing up your current project. Pipx has an isolated environment so it doesn't tinker with your local virtual environment or project. Though you can use your current project to use those CLI to execute commands which might require the source file in the project.

We can even print the markdown file in a rich format, simply using pipx and rich-cli. There are a lot of things we can do with rich-cli.

```
pipx run rich-cli <markdown_file.md>
```

![rich-cli markdown demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647785474/blog-media/bwmvucrcgrtgwdv58ffj.png)

For further reading on the rich-cli package, you visit their [GitHub](https://github.com/Textualize/rich-cli) link and the [Documentation](https://github.com/Textualize/rich-cli/blob/main/README.md) Readme.

### Using pytest to perform a test for the current project

[Pytest](https://pypi.org/project/pytest/) allows writing simple and scalable tests for Python apps, libraries, and packages. We can use it to write tests in the project without adding it as a dependency in the python environment. Simply install the package with pipx and run the tests in an isolated environment.

```
pipx install pytest

pipx run pytest temp.py
```

![Pytest pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782771/blog-media/qutb0bxzlnwctl9mbuon.png)

Here, we can see the pytest was performed on the `temp.py` file which can be any application file for your project. This gave us results without installing pytest in our application's virtual environment. This becomes really convenient to run certain package commands whose package should not be a dependency on your project in the virtual environment.

You can visit Pytest's [GitHub](https://github.com/pytest-dev/pytest/), [Documentation](https://docs.pytest.org/en/stable/) and their [Home Page](https://pytest.org/).

### Using Black (Python code formatter)

We can use pipx to even format the python source files using [black](https://pypi.org/project/black/). We don't have to install `black` as a dependency in the project. Pipx will simply install black in its isolated environment and run the specified command.

```
pipx install black

pipx run black temp.py
```

![Black pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782823/blog-media/dtnae85fvgae2y4aiqkg.png)

Black is a code formatter in Python, it basically edits your source python files for any incorrect python semantics and syntax, it corrects/formats them without a compromise. You can visit the [GitHub](https://github.com/psf/black), [Documentation](https://black.readthedocs.io/en/stable) or the Black package [Playground webpage](https://black.vercel.app/).

### Using httpie (curl equivalent in Python)

We can use the [httpie](https://pypi.org/project/httpie/) package in python which is a CLI tool for HTTP clients. It is very similar to the `curl` command in Linux. We can even use that with pipx to test out API endpoints or any website that you might be working with without leaving the terminal. For further details on the httpie package, you can visit their [Home page](https://httpie.io/), [GitHub](https://github.com/httpie), or [PyPI webpage](https://pypi.org/project/httpie/). 

```
pipx install httpie

pipx run --spec httpie http -v dev.to
```

![httpie pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647782857/blog-media/jbaudm3pbnnsjtzy5ok7.png)

Here, we can see the package simply gives a simple output of the headers of the request. It is smart enough to understand the web link as `https://dev.to` unlike CURL which needs to have an exact match.

### Running Markata blog with pipx 

As said, every package that bundles itself with a CLI can be installed and run from anywhere. So, [markata](https://pypi.org/project/markata/) which is a plugin-driven static site generator which is a python package also bundles with a CLI. Using the base app(markata) we can run its associated commands like `build`, `list`, etc. I use this to build my blog.

```
pipx install markata

pipx run markata build
```

![Markata pipx demo](https://res.cloudinary.com/techstructive-blog/image/upload/v1647783021/blog-media/cygzwixyzwv4wwsccbfc.gif)

You can visit the Markata's [documentation](https://markata.dev/) web page or the [GitHub](https://github.com/WaylonWalker/markata) repository for further insights on the Static site generator.

**If you want to explore more packages that you can use with pipx, then you can look at the docs guide [programs-to-try](https://pypa.github.io/pipx/programs-to-try/) section.**

## Conclusion

So, from this simple introduction, we were able to understand the basics of pipx which is a python package for isolating and running CLI-specific package commands. We saw how to setup pipx, install packages, run the commands from the package and interact with the virtual environment that it creates for each package we install. 

Thank you for reading, if you have any comments, suggestions, feedback please let me know in the comments. Happy Coding :)