$ ln -s /opt/work/my-env/../../../usr/local/bin/within-venv.sh /opt/within-my-venv && ln -s /opt/within-my-venv /usr/local/bin/mytool
$ mytool # runs in /opt/work/my-venv
Last active
August 29, 2019 18:42
-
-
Save maxwellb/002d06664b522798c2352fe395af397d to your computer and use it in GitHub Desktop.
Universal Python venv wrapper
- Create a virtual env in a directory. Example:
python3 -m venv /opt/work/my-venv
- Create a symbolic link to this script on your PATH, in a special way:
- The source of the link must be this script, as a relative path to the virtual environment to run within.
- The name of the link should be an executable file within the
bin/
directory of the virtual environment. Example:ln -s /opt/work/my-env/../../../usr/local/bin/within-venv.sh /usr/local/bin/mytool
- Alternatively, create a "wrapper link" from the relative path to this script from the virtual environment.
Then, create a link named after your target executable to this link.
Example:
ln -s /opt/work/my-env/../../../usr/local/bin/within-venv.sh /opt/within-my-venv && ln -s /opt/within-my-venv /usr/local/bin/mytool
You are running this script. The script then runs mytool
(or your link name) after adding your virtual
environment's bin/
directory to the PATH. It determines the correct PATH by inspecting the special way
you created the link.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Copyright Maxwell Bloch 2019 | |
# Licensed GPL version 2 or later | |
unwind() { | |
path=${1} | |
path=$(dirname ${path}) | |
while [ "$(basename ${path})" != ".." ]; do | |
path=$(dirname ${path}) | |
done | |
while [ "$(basename ${path})" = ".." ]; do | |
path=$(dirname ${path}) | |
done | |
echo ${path} | |
} | |
if [ -L ${0} -a -f ${0} ]; then | |
script="$(basename ${0})" | |
wrapper=${0} | |
dirname=$(readlink -f $(dirname ${wrapper})) | |
while [ -L ${wrapper} ]; do | |
wrapper=$(readlink ${wrapper}) | |
if [ "$(echo ${wrapper} | cut -c1)" != "/" ]; then | |
wrapper="${dirname}/${wrapper}" | |
fi | |
done | |
path="$(unwind ${wrapper})" | |
fi | |
if [ -x ${path}/bin/${script} ]; then | |
PATH="${path}/bin:$PATH" ${path}/bin/${script} "$@" | |
else | |
echo "Script or program '${script}' not found in path ${path}/bin" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment