ยง Pipenv + fzf tandem

More often than not I find myself wanting to reuse a python virtual environment with packages I use frequently already installed. For instance, I might want to do some quick calculations and plotting in a scratch directory with numpy, scipy, pandas, matplotlib, etc. With my current python workflow, it is easy to lie on a Procrustean bed and create a new virtual environment in each and every new scratch directory. Alternatively, one could create a base virtual environment, install the aforementioned packages and source the virtual environment from where ever it is located and carry on with one’s calculations and plots.

This latter option is slightly less cumbersome than the former, but it still requires you to know where the base virtual environment is located. With pipenv and fzf we can lift the mental overhead of having to knowing where the base virtual environment is. To this end, I wrote a script that uses fzf to source a pipenv-managed virtual environment from anywhere.


#!/bin/sh

# activates a virtualenv managed by pipenv in the current directory

# collect of all pipenv-managed virtual environments
path="$HOME/.local/share/virtualenvs"
venv_paths=("$path"/*)
project_paths=("$path"/*)

# shorten paths to project that created
# the virtual environment, which is stored
# inside the .project file of the corresponding
# virtual environment
for (( i=0; i<${#venv_paths[@]}; i++ )); do
    project_path=$(cat "${venv_paths[i]}"/.project)
    project_path="${project_path}"
    project_path="${project_path##*/}"
    project_paths[i]="${project_path}"
done

# select project with fzf
sel_proj=$(printf "%s\n" "${project_paths[@]}" | fzf)

# exit if nothing selected
if [ -z "$sel_proj" ]; then
    exit 0
fi

# get index of virtual environment
# that corresponds to selected project
for i in "${!project_paths[@]}"; do
   [[ "${project_paths[$i]}" = "${sel_proj}" ]] && break
done

# source virtual environment, and spawn new shell with
# the virtual environment activated
. "${venv_paths[i]}/bin/activate"
$SHELL