Skip to main content

venvx: Managing Multiple Python *2* Virtual Environments

Introduction

venvx is a sort of minimal combination of pipx and pew. It can be used in the development and testing of tools that exist in separate virtualenv virtual environments (similar to pew). It also has to ability to simply run console entrypoints that exist in other environments. Similar to pipx, venvx also has a run command that will build a new virtualenv just for the invocation of the command.

This script is minimal, meaning its not efficient or polished, but at this point can we really say anything in Python 2 is polished? This is a stop gap for projects that need to support npx like interfaces without the open source support.

Activating venvx

Similar to virtualenv, its assumed that you'll be activating the script by sourcing in the script. This isn't strictly required, but significantly improves the user experience. Assuming this script is stored as something like venvx.sh, activate by running:

source venvx.sh

Once activated you'll have access to primary entrypoint of the tool: venvx.

Create A New Environment

venvx new mytool

This will create a new virtualenv named mytool in the $WORKON_HOME folder. Note: $WORKON_HOME defaults to your current working directory plus venv. Therefore if you activate venvx from the home directory, $WORKON_HOME will default to ~/venv/ and mytool will be generated in ~/venv/mytool.

As part of the venvx environment creation, it will automatically install pip and pipenv. This is intended to encourage usage of pipenv's lock files.

Execute Entrypoint In Another Environment

venvx in mytool <command> [arguments]

This simply sets up the environment such that the given command and arguments will think that its running from the specified virtual environment.

Activate VirtualEnv Environment

venvx workon mytool

When developing or testing and you don't want to prefix your commands with venv in <venv>, you can opt to activate the virtualenv. Instead of running yet another long ugly command (source <venv>/bin/activate), you simply run venvx workon <venv> which is intended to be more expressive and easy to remember. This is the same syntax as pew so it travels to Python 3 well when you need to context switch.

You can always keep switching between your various virtualenv's or you can deactivate with a simple deactivate.

Run Command Without Virtualenv

venvx run <entrypoint>

This command assumes that the entry point being run matches the name of the package. But if this assumption is met it means that you can run commands without having to worry about installing them into your global user pip site-packages or worrying about managing a virtualenv just for the command.

Seeing as this command is very simple, it literally rebuilds the virtualenv for each invocation of the entry point. With pip caching this can be slow the first time, but should be a quicker process in subsequent operations, but not lightweight or efficient to say the least.

Uninstalling venvx

venvx deactivate

Run the above command to remove venvx from your current environment. I don't know why you'd want to do this ;-), but its good to have symmetry.

venvx Shell Script

#!/bin/bash

WORKON_HOME=${WORKON_HOME:-$(realpath venv)}

function venvx() {
action=$1
shift

if [ "$action" == "in" ]; then
venv=$1
shift
VIRTUAL_ENV="${WORKON_HOME}/$venv" \
PATH="${WORKON_HOME}/$venv/bin:$PATH" \
${*}
elif [ "$action" == "new" ]; then
venv=$1
shift
echo "Creating virtualenv: $venv"
virtualenv -q ${WORKON_HOME}/$venv
venvx in $venv pip -q install -U pip pipenv
elif [ "$action" == "run" ]; then
pkg=$1
tmppath=$(mktemp -d --tmpdir="${WORKON_HOME}" -t .tmp.XXXXXXXXXX)
shift
echo "Creating temporary virtualenv for: $pkg"
venvx new $tmppath
venvx in $tmppath pip -q install -U $pkg
venvx in $tmppath $pkg ${*}
rm -rf $tmppath
elif [ "$action" == "workon" ]; then
venvx_type=$(type -t venvx)
if [ "$venvx_type" != "function" ]; then
echo "venvx workon requires venvx to be sourced"
else
venv=$1
shift
source ${WORKON_HOME}/$venv/bin/activate
fi
elif [ "$action" == "deactivate" ]; then
venvx_type=$(type -t venvx)
if [ "$venvx_type" != "function" ]; then
echo "venvx deactivate requires venvx to be sourced"
else
unset -f venvx
fi
else
echo "venvx <action> [options]"
echo
echo "Actions:"
echo " - in ........... Executes commands within given virtual environment."
echo " - new .......... Creates a new empty virtual environment."
echo " - run .......... Creates a new virtualenv to run pkg entrypoint."
echo " - workon ....... Activates the specified virtualenv."
echo " - deactivate ... Removes venvx from environment."
echo " - help ......... Displays this help message."
echo
fi
}

[[ $_ != $0 ]] && echo "\`venvx\` activation complete." || venvx $@

Comments